@@ -24,6 +24,7 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.sufficientlysecure.keychain.securitytoken.KeyFormat;
|
||||
import org.sufficientlysecure.keychain.securitytoken.RSAKeyFormat;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.Proxy;
|
||||
@@ -178,12 +179,12 @@ public final class Constants {
|
||||
/**
|
||||
* Default key configuration: 3072 bit RSA (certify, sign, encrypt)
|
||||
*/
|
||||
public static void addDefaultSubkeys(SaveKeyringParcel saveKeyringParcel) {
|
||||
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
|
||||
public static void addDefaultSubkeys(SaveKeyringParcel.Builder builder) {
|
||||
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
|
||||
3072, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
|
||||
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
|
||||
3072, null, KeyFlags.SIGN_DATA, 0L));
|
||||
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
|
||||
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
|
||||
3072, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L));
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ public class ImportKeysListCloudLoader
|
||||
mEntryList.clear();
|
||||
GetKeyResult pendingResult = new GetKeyResult(null,
|
||||
RequiredInputParcel.createOrbotRequiredOperation(),
|
||||
new CryptoInputParcel());
|
||||
CryptoInputParcel.createCryptoInputParcel());
|
||||
mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, pendingResult);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ import org.sufficientlysecure.keychain.util.Log;
|
||||
* This class receives a source and/or destination of keys as input and performs
|
||||
* all steps for this backup.
|
||||
*
|
||||
* @see org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter#getSelectedEntries()
|
||||
* see org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter#getSelectedEntries()
|
||||
* For the backup operation, the input consists of a set of key ids and
|
||||
* either the name of a file or an output uri to write to.
|
||||
*/
|
||||
@@ -104,8 +104,8 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
||||
OutputStream outputStream) {
|
||||
|
||||
OperationLog log = new OperationLog();
|
||||
if (backupInput.mMasterKeyIds != null) {
|
||||
log.add(LogType.MSG_BACKUP, 0, backupInput.mMasterKeyIds.length);
|
||||
if (backupInput.getMasterKeyIds() != null) {
|
||||
log.add(LogType.MSG_BACKUP, 0, backupInput.getMasterKeyIds().length);
|
||||
} else {
|
||||
log.add(LogType.MSG_BACKUP_ALL, 0);
|
||||
}
|
||||
@@ -113,7 +113,7 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
||||
try {
|
||||
Uri plainUri = null;
|
||||
OutputStream plainOut;
|
||||
if (backupInput.mIsEncrypted) {
|
||||
if (backupInput.getIsEncrypted()) {
|
||||
if (cryptoInput == null) {
|
||||
throw new IllegalStateException("Encrypted backup must supply cryptoInput parameter");
|
||||
}
|
||||
@@ -121,23 +121,23 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
||||
plainUri = TemporaryFileProvider.createFile(mContext);
|
||||
plainOut = mContext.getContentResolver().openOutputStream(plainUri);
|
||||
} else {
|
||||
if (backupInput.mOutputUri == null || outputStream != null) {
|
||||
if (backupInput.getOutputUri() == null || outputStream != null) {
|
||||
throw new IllegalArgumentException("Unencrypted export to output stream is not supported!");
|
||||
} else {
|
||||
plainOut = mContext.getContentResolver().openOutputStream(backupInput.mOutputUri);
|
||||
plainOut = mContext.getContentResolver().openOutputStream(backupInput.getOutputUri());
|
||||
}
|
||||
}
|
||||
|
||||
CountingOutputStream outStream = new CountingOutputStream(new BufferedOutputStream(plainOut));
|
||||
boolean backupSuccess = exportKeysToStream(
|
||||
log, backupInput.mMasterKeyIds, backupInput.mExportSecret, outStream);
|
||||
log, backupInput.getMasterKeyIds(), backupInput.getExportSecret(), outStream);
|
||||
|
||||
if (!backupSuccess) {
|
||||
// if there was an error, it will be in the log so we just have to return
|
||||
return new ExportResult(ExportResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
if (!backupInput.mIsEncrypted) {
|
||||
if (!backupInput.getIsEncrypted()) {
|
||||
// log.add(LogType.MSG_EXPORT_NO_ENCRYPT, 1);
|
||||
log.add(LogType.MSG_BACKUP_SUCCESS, 1);
|
||||
return new ExportResult(ExportResult.RESULT_OK, log);
|
||||
@@ -170,27 +170,29 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
||||
throws FileNotFoundException {
|
||||
PgpSignEncryptOperation signEncryptOperation = new PgpSignEncryptOperation(mContext, mKeyRepository, mProgressable, mCancelled);
|
||||
|
||||
PgpSignEncryptData data = new PgpSignEncryptData();
|
||||
data.setSymmetricPassphrase(cryptoInput.getPassphrase());
|
||||
data.setEnableAsciiArmorOutput(backupInput.mEnableAsciiArmorOutput);
|
||||
data.setAddBackupHeader(true);
|
||||
PgpSignEncryptInputParcel inputParcel = new PgpSignEncryptInputParcel(data);
|
||||
PgpSignEncryptData.Builder builder = PgpSignEncryptData.builder();
|
||||
builder.setSymmetricPassphrase(cryptoInput.getPassphrase());
|
||||
builder.setEnableAsciiArmorOutput(backupInput.getEnableAsciiArmorOutput());
|
||||
builder.setAddBackupHeader(true);
|
||||
PgpSignEncryptData pgpSignEncryptData = builder.build();
|
||||
|
||||
InputStream inStream = mContext.getContentResolver().openInputStream(plainUri);
|
||||
|
||||
String filename;
|
||||
if (backupInput.mMasterKeyIds != null && backupInput.mMasterKeyIds.length == 1) {
|
||||
filename = Constants.FILE_BACKUP_PREFIX + KeyFormattingUtils.convertKeyIdToHex(backupInput.mMasterKeyIds[0]);
|
||||
long[] masterKeyIds = backupInput.getMasterKeyIds();
|
||||
if (masterKeyIds != null && masterKeyIds.length == 1) {
|
||||
filename = Constants.FILE_BACKUP_PREFIX + KeyFormattingUtils.convertKeyIdToHex(
|
||||
masterKeyIds[0]);
|
||||
} else {
|
||||
filename = Constants.FILE_BACKUP_PREFIX + new SimpleDateFormat("yyyy-MM-dd", Locale
|
||||
.getDefault()).format(new Date());
|
||||
}
|
||||
filename += backupInput.mExportSecret ? Constants.FILE_EXTENSION_BACKUP_SECRET : Constants.FILE_EXTENSION_BACKUP_PUBLIC;
|
||||
filename += backupInput.getExportSecret() ? Constants.FILE_EXTENSION_BACKUP_SECRET : Constants.FILE_EXTENSION_BACKUP_PUBLIC;
|
||||
|
||||
InputData inputData = new InputData(inStream, exportedDataSize, filename);
|
||||
|
||||
OutputStream outStream;
|
||||
if (backupInput.mOutputUri == null) {
|
||||
if (backupInput.getOutputUri() == null) {
|
||||
if (outputStream == null) {
|
||||
throw new IllegalArgumentException("If output uri is not set, outputStream must not be null!");
|
||||
}
|
||||
@@ -199,10 +201,11 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
||||
if (outputStream != null) {
|
||||
throw new IllegalArgumentException("If output uri is set, outputStream must null!");
|
||||
}
|
||||
outStream = mContext.getContentResolver().openOutputStream(backupInput.mOutputUri);
|
||||
outStream = mContext.getContentResolver().openOutputStream(backupInput.getOutputUri());
|
||||
}
|
||||
|
||||
return signEncryptOperation.execute(inputParcel, new CryptoInputParcel(), inputData, outStream);
|
||||
return signEncryptOperation.execute(
|
||||
pgpSignEncryptData, CryptoInputParcel.createCryptoInputParcel(), inputData, outStream);
|
||||
}
|
||||
|
||||
boolean exportKeysToStream(OperationLog log, long[] masterKeyIds, boolean exportSecret, OutputStream outStream) {
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
|
||||
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
||||
@@ -83,12 +82,11 @@ public class BenchmarkOperation extends BaseOperation<BenchmarkInputParcel> {
|
||||
SignEncryptOperation op =
|
||||
new SignEncryptOperation(mContext, mKeyRepository,
|
||||
new ProgressScaler(mProgressable, i*(50/numRepeats), (i+1)*(50/numRepeats), 100), mCancelled);
|
||||
PgpSignEncryptData data = new PgpSignEncryptData();
|
||||
PgpSignEncryptData.Builder data = PgpSignEncryptData.builder();
|
||||
data.setSymmetricPassphrase(passphrase);
|
||||
data.setSymmetricEncryptionAlgorithm(OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
|
||||
SignEncryptParcel input = new SignEncryptParcel(data);
|
||||
input.setBytes(buf);
|
||||
encryptResult = op.execute(input, new CryptoInputParcel());
|
||||
data.setSymmetricEncryptionAlgorithm(SymmetricKeyAlgorithmTags.AES_128);
|
||||
SignEncryptParcel input = SignEncryptParcel.createSignEncryptParcel(data.build(), buf);
|
||||
encryptResult = op.execute(input, CryptoInputParcel.createCryptoInputParcel());
|
||||
log.add(encryptResult, 1);
|
||||
log.add(LogType.MSG_BENCH_ENC_TIME, 2,
|
||||
String.format("%.2f", encryptResult.getResults().get(0).mOperationTime / 1000.0));
|
||||
@@ -105,9 +103,10 @@ public class BenchmarkOperation extends BaseOperation<BenchmarkInputParcel> {
|
||||
PgpDecryptVerifyOperation op =
|
||||
new PgpDecryptVerifyOperation(mContext, mKeyRepository,
|
||||
new ProgressScaler(mProgressable, 50 +i*(50/numRepeats), 50 +(i+1)*(50/numRepeats), 100));
|
||||
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(encryptResult.getResultBytes());
|
||||
input.setAllowSymmetricDecryption(true);
|
||||
decryptResult = op.execute(input, new CryptoInputParcel(passphrase));
|
||||
PgpDecryptVerifyInputParcel.Builder builder = PgpDecryptVerifyInputParcel.builder()
|
||||
.setInputBytes(encryptResult.getResultBytes())
|
||||
.setAllowSymmetricDecryption(true);
|
||||
decryptResult = op.execute(builder.build(), CryptoInputParcel.createCryptoInputParcel(passphrase));
|
||||
log.add(decryptResult, 1);
|
||||
log.add(LogType.MSG_BENCH_DEC_TIME, 2, String.format("%.2f", decryptResult.mOperationTime / 1000.0));
|
||||
totalTime += decryptResult.mOperationTime;
|
||||
|
||||
@@ -76,7 +76,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
||||
|
||||
// Retrieve and unlock secret key
|
||||
CanonicalizedSecretKey certificationKey;
|
||||
long masterKeyId = parcel.mMasterKeyId;
|
||||
long masterKeyId = parcel.getMasterKeyId();
|
||||
try {
|
||||
|
||||
log.add(LogType.MSG_CRT_MASTER_FETCH, 1);
|
||||
@@ -121,7 +121,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
||||
|
||||
// Get actual secret key
|
||||
CanonicalizedSecretKeyRing secretKeyRing =
|
||||
mKeyRepository.getCanonicalizedSecretKeyRing(parcel.mMasterKeyId);
|
||||
mKeyRepository.getCanonicalizedSecretKeyRing(parcel.getMasterKeyId());
|
||||
certificationKey = secretKeyRing.getSecretKey();
|
||||
|
||||
log.add(LogType.MSG_CRT_UNLOCK, 1);
|
||||
@@ -148,7 +148,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
||||
cryptoInput.getSignatureTime(), masterKeyId, masterKeyId);
|
||||
|
||||
// Work through all requested certifications
|
||||
for (CertifyAction action : parcel.mCertifyActions) {
|
||||
for (CertifyAction action : parcel.getCertifyActions()) {
|
||||
|
||||
// Check if we were cancelled
|
||||
if (checkCancelled()) {
|
||||
@@ -158,14 +158,14 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
||||
|
||||
try {
|
||||
|
||||
if (action.mMasterKeyId == parcel.mMasterKeyId) {
|
||||
if (action.getMasterKeyId() == parcel.getMasterKeyId()) {
|
||||
log.add(LogType.MSG_CRT_ERROR_SELF, 2);
|
||||
certifyError += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
CanonicalizedPublicKeyRing publicRing =
|
||||
mKeyRepository.getCanonicalizedPublicKeyRing(action.mMasterKeyId);
|
||||
mKeyRepository.getCanonicalizedPublicKeyRing(action.getMasterKeyId());
|
||||
|
||||
PgpCertifyOperation op = new PgpCertifyOperation();
|
||||
PgpCertifyResult result = op.certify(certificationKey, publicRing,
|
||||
@@ -205,7 +205,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
||||
|
||||
// these variables are used inside the following loop, but they need to be created only once
|
||||
UploadOperation uploadOperation = null;
|
||||
if (parcel.keyServerUri != null) {
|
||||
if (parcel.getParcelableKeyServer() != null) {
|
||||
uploadOperation = new UploadOperation(mContext, mKeyRepository, mProgressable, mCancelled);
|
||||
}
|
||||
|
||||
@@ -226,8 +226,8 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
||||
SaveKeyringResult result = mKeyWritableRepository.savePublicKeyRing(certifiedKey);
|
||||
|
||||
if (uploadOperation != null) {
|
||||
UploadKeyringParcel uploadInput =
|
||||
new UploadKeyringParcel(parcel.keyServerUri, certifiedKey.getMasterKeyId());
|
||||
UploadKeyringParcel uploadInput = UploadKeyringParcel.createWithKeyId(
|
||||
parcel.getParcelableKeyServer(), certifiedKey.getMasterKeyId());
|
||||
UploadResult uploadResult = uploadOperation.execute(uploadInput, cryptoInput);
|
||||
log.add(uploadResult, 2);
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ChangeUnlockOperation extends BaseReadWriteOperation<ChangeUnlockPa
|
||||
OperationResult.OperationLog log = new OperationResult.OperationLog();
|
||||
log.add(OperationResult.LogType.MSG_ED, 0);
|
||||
|
||||
if (unlockParcel == null || unlockParcel.mMasterKeyId == null) {
|
||||
if (unlockParcel == null || unlockParcel.getMasterKeyId() == null) {
|
||||
log.add(OperationResult.LogType.MSG_ED_ERROR_NO_PARCEL, 1);
|
||||
return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
@@ -60,10 +60,10 @@ public class ChangeUnlockOperation extends BaseReadWriteOperation<ChangeUnlockPa
|
||||
|
||||
try {
|
||||
log.add(OperationResult.LogType.MSG_ED_FETCHING, 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(unlockParcel.mMasterKeyId));
|
||||
KeyFormattingUtils.convertKeyIdToHex(unlockParcel.getMasterKeyId()));
|
||||
|
||||
CanonicalizedSecretKeyRing secRing =
|
||||
mKeyRepository.getCanonicalizedSecretKeyRing(unlockParcel.mMasterKeyId);
|
||||
mKeyRepository.getCanonicalizedSecretKeyRing(unlockParcel.getMasterKeyId());
|
||||
modifyResult = keyOperations.modifyKeyRingPassphrase(secRing, cryptoInput, unlockParcel);
|
||||
|
||||
if (modifyResult.isPending()) {
|
||||
|
||||
@@ -39,7 +39,7 @@ public class ConsolidateOperation extends BaseReadWriteOperation<ConsolidateInpu
|
||||
@Override
|
||||
public ConsolidateResult execute(ConsolidateInputParcel consolidateInputParcel,
|
||||
CryptoInputParcel cryptoInputParcel) {
|
||||
if (consolidateInputParcel.mConsolidateRecovery) {
|
||||
if (consolidateInputParcel.isStartFromRecovery()) {
|
||||
return mKeyWritableRepository.consolidateDatabaseStep2(mProgressable);
|
||||
} else {
|
||||
return mKeyWritableRepository.consolidateDatabaseStep1(mProgressable);
|
||||
|
||||
@@ -52,8 +52,8 @@ public class DeleteOperation extends BaseReadWriteOperation<DeleteKeyringParcel>
|
||||
public OperationResult execute(DeleteKeyringParcel deleteKeyringParcel,
|
||||
CryptoInputParcel cryptoInputParcel) {
|
||||
|
||||
long[] masterKeyIds = deleteKeyringParcel.mMasterKeyIds;
|
||||
boolean isSecret = deleteKeyringParcel.mIsSecret;
|
||||
long[] masterKeyIds = deleteKeyringParcel.getMasterKeyIds();
|
||||
boolean isSecret = deleteKeyringParcel.isDeleteSecret();
|
||||
|
||||
return onlyDeleteKey(masterKeyIds, isSecret);
|
||||
}
|
||||
|
||||
@@ -88,13 +88,13 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
|
||||
new PgpKeyOperation(new ProgressScaler(mProgressable, 10, 60, 100), mCancelled);
|
||||
|
||||
// If a key id is specified, fetch and edit
|
||||
if (saveParcel.mMasterKeyId != null) {
|
||||
if (saveParcel.getMasterKeyId() != null) {
|
||||
try {
|
||||
|
||||
log.add(LogType.MSG_ED_FETCHING, 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(saveParcel.mMasterKeyId));
|
||||
KeyFormattingUtils.convertKeyIdToHex(saveParcel.getMasterKeyId()));
|
||||
CanonicalizedSecretKeyRing secRing =
|
||||
mKeyRepository.getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId);
|
||||
mKeyRepository.getCanonicalizedSecretKeyRing(saveParcel.getMasterKeyId());
|
||||
|
||||
modifyResult = keyOperations.modifySecretKeyRing(secRing, cryptoInput, saveParcel);
|
||||
if (modifyResult.isPending()) {
|
||||
@@ -133,7 +133,7 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
|
||||
// It's a success, so this must be non-null now
|
||||
UncachedKeyRing ring = modifyResult.getRing();
|
||||
|
||||
if (saveParcel.isUpload()) {
|
||||
if (saveParcel.isShouldUpload()) {
|
||||
byte[] keyringBytes;
|
||||
try {
|
||||
UncachedKeyRing publicKeyRing = ring.extractPublicKeyRing();
|
||||
@@ -144,7 +144,7 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
|
||||
}
|
||||
|
||||
UploadKeyringParcel exportKeyringParcel =
|
||||
new UploadKeyringParcel(saveParcel.getUploadKeyserver(), keyringBytes);
|
||||
UploadKeyringParcel.createWithKeyringBytes(saveParcel.getUploadKeyserver(), keyringBytes);
|
||||
|
||||
UploadResult uploadResult = new UploadOperation(
|
||||
mContext, mKeyRepository, new ProgressScaler(mProgressable, 60, 80, 100), mCancelled)
|
||||
@@ -154,7 +154,7 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
|
||||
|
||||
if (uploadResult.isPending()) {
|
||||
return new EditKeyResult(log, uploadResult);
|
||||
} else if (!uploadResult.success() && saveParcel.isUploadAtomic()) {
|
||||
} else if (!uploadResult.success() && saveParcel.isShouldUploadAtomic()) {
|
||||
// if atomic, update fail implies edit operation should also fail and not save
|
||||
return new EditKeyResult(log, RequiredInputParcel.createRetryUploadOperation(), cryptoInput);
|
||||
}
|
||||
|
||||
@@ -469,9 +469,9 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
||||
@NonNull
|
||||
@Override
|
||||
public ImportKeyResult execute(ImportKeyringParcel importInput, CryptoInputParcel cryptoInput) {
|
||||
ArrayList<ParcelableKeyRing> keyList = importInput.mKeyList;
|
||||
ParcelableHkpKeyserver keyServer = importInput.mKeyserver;
|
||||
boolean skipSave = importInput.mSkipSave;
|
||||
ArrayList<ParcelableKeyRing> keyList = importInput.getKeyList();
|
||||
ParcelableHkpKeyserver keyServer = importInput.getKeyserver();
|
||||
boolean skipSave = importInput.isSkipSave();
|
||||
|
||||
ImportKeyResult result;
|
||||
if (keyList == null) {// import from file, do serially
|
||||
@@ -495,7 +495,7 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
||||
result = multiThreadedKeyImport(keyList, keyServer, proxy, skipSave);
|
||||
}
|
||||
|
||||
if (!importInput.mSkipSave) {
|
||||
if (!skipSave) {
|
||||
ContactSyncAdapterService.requestContactsSync();
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -103,10 +103,12 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
|
||||
PgpDecryptVerifyOperation op =
|
||||
new PgpDecryptVerifyOperation(mContext, mKeyRepository, mProgressable);
|
||||
|
||||
decryptInput.setInputUri(input.getInputUri());
|
||||
|
||||
currentInputUri = TemporaryFileProvider.createFile(mContext);
|
||||
decryptInput.setOutputUri(currentInputUri);
|
||||
|
||||
decryptInput = decryptInput.toBuilder()
|
||||
.setInputUri(input.getInputUri())
|
||||
.setOutputUri(currentInputUri)
|
||||
.build();
|
||||
|
||||
decryptResult = op.execute(decryptInput, cryptoInput);
|
||||
if (decryptResult.isPending()) {
|
||||
@@ -264,9 +266,10 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
|
||||
}
|
||||
detachedSig.close();
|
||||
|
||||
PgpDecryptVerifyInputParcel decryptInput = new PgpDecryptVerifyInputParcel();
|
||||
decryptInput.setInputUri(uncheckedSignedDataUri);
|
||||
decryptInput.setDetachedSignature(detachedSig.toByteArray());
|
||||
PgpDecryptVerifyInputParcel decryptInput = PgpDecryptVerifyInputParcel.builder()
|
||||
.setInputUri(uncheckedSignedDataUri)
|
||||
.setDetachedSignature(detachedSig.toByteArray())
|
||||
.build();
|
||||
|
||||
PgpDecryptVerifyOperation op =
|
||||
new PgpDecryptVerifyOperation(mContext, mKeyRepository, mProgressable);
|
||||
|
||||
@@ -152,9 +152,11 @@ public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificat
|
||||
|
||||
PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(mContext, mKeyRepository, mProgressable);
|
||||
|
||||
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(messageBytes);
|
||||
PgpDecryptVerifyInputParcel input = PgpDecryptVerifyInputParcel.builder()
|
||||
.setInputBytes(messageBytes)
|
||||
.build();
|
||||
|
||||
DecryptVerifyResult decryptVerifyResult = op.execute(input, new CryptoInputParcel());
|
||||
DecryptVerifyResult decryptVerifyResult = op.execute(input, CryptoInputParcel.createCryptoInputParcel());
|
||||
|
||||
if (!decryptVerifyResult.success()) {
|
||||
log.add(decryptVerifyResult, 1);
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.service.PromoteKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||
|
||||
/** An operation which promotes a public key ring to a secret one.
|
||||
*
|
||||
@@ -67,17 +66,18 @@ public class PromoteKeyOperation extends BaseReadWriteOperation<PromoteKeyringPa
|
||||
try {
|
||||
|
||||
log.add(LogType.MSG_PR_FETCHING, 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(promoteKeyringParcel.mKeyRingId));
|
||||
KeyFormattingUtils.convertKeyIdToHex(promoteKeyringParcel.getMasterKeyId()));
|
||||
CanonicalizedPublicKeyRing pubRing =
|
||||
mKeyRepository.getCanonicalizedPublicKeyRing(promoteKeyringParcel.mKeyRingId);
|
||||
mKeyRepository.getCanonicalizedPublicKeyRing(promoteKeyringParcel.getMasterKeyId());
|
||||
|
||||
if (promoteKeyringParcel.mSubKeyIds == null) {
|
||||
long[] subKeyIds = promoteKeyringParcel.getSubKeyIds();
|
||||
if (subKeyIds == null) {
|
||||
log.add(LogType.MSG_PR_ALL, 1);
|
||||
} else {
|
||||
// sort for binary search
|
||||
for (CanonicalizedPublicKey key : pubRing.publicKeyIterator()) {
|
||||
long subKeyId = key.getKeyId();
|
||||
if (naiveIndexOf(promoteKeyringParcel.mSubKeyIds, subKeyId) != null) {
|
||||
if (naiveIndexOf(subKeyIds, subKeyId) != null) {
|
||||
log.add(LogType.MSG_PR_SUBKEY_MATCH, 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(subKeyId));
|
||||
} else {
|
||||
@@ -88,8 +88,7 @@ public class PromoteKeyOperation extends BaseReadWriteOperation<PromoteKeyringPa
|
||||
}
|
||||
|
||||
// create divert-to-card secret key from public key
|
||||
promotedRing = pubRing.createDivertSecretRing(promoteKeyringParcel.mCardAid,
|
||||
promoteKeyringParcel.mSubKeyIds);
|
||||
promotedRing = pubRing.createDivertSecretRing(promoteKeyringParcel.getCardAid(), subKeyIds);
|
||||
|
||||
} catch (NotFoundException e) {
|
||||
log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2);
|
||||
|
||||
@@ -51,9 +51,9 @@ public class RevokeOperation extends BaseReadWriteOperation<RevokeKeyringParcel>
|
||||
CryptoInputParcel cryptoInputParcel) {
|
||||
|
||||
// we don't cache passphrases during revocation
|
||||
cryptoInputParcel.mCachePassphrase = false;
|
||||
cryptoInputParcel = cryptoInputParcel.withNoCachePassphrase();
|
||||
|
||||
long masterKeyId = revokeKeyringParcel.mMasterKeyId;
|
||||
long masterKeyId = revokeKeyringParcel.getMasterKeyId();
|
||||
|
||||
OperationResult.OperationLog log = new OperationResult.OperationLog();
|
||||
log.add(OperationResult.LogType.MSG_REVOKE, 0,
|
||||
@@ -71,17 +71,18 @@ public class RevokeOperation extends BaseReadWriteOperation<RevokeKeyringParcel>
|
||||
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
|
||||
}
|
||||
|
||||
SaveKeyringParcel saveKeyringParcel =
|
||||
new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
|
||||
SaveKeyringParcel.Builder saveKeyringParcel =
|
||||
SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
|
||||
|
||||
// all revoke operations are made atomic as of now
|
||||
saveKeyringParcel.setUpdateOptions(revokeKeyringParcel.mUpload, true,
|
||||
revokeKeyringParcel.mKeyserver);
|
||||
saveKeyringParcel.setUpdateOptions(revokeKeyringParcel.isShouldUpload(), true,
|
||||
revokeKeyringParcel.getKeyserver());
|
||||
|
||||
saveKeyringParcel.mRevokeSubKeys.add(masterKeyId);
|
||||
saveKeyringParcel.addRevokeSubkey(masterKeyId);
|
||||
|
||||
EditKeyResult revokeAndUploadResult = new EditKeyOperation(mContext,
|
||||
mKeyWritableRepository, mProgressable, mCancelled).execute(saveKeyringParcel, cryptoInputParcel);
|
||||
mKeyWritableRepository, mProgressable, mCancelled).execute(
|
||||
saveKeyringParcel.build(), cryptoInputParcel);
|
||||
|
||||
if (revokeAndUploadResult.isPending()) {
|
||||
return revokeAndUploadResult;
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
|
||||
@@ -36,13 +35,11 @@ import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenSignOperationsBuilder;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||
|
||||
|
||||
@@ -76,20 +73,6 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
|
||||
|
||||
SecurityTokenSignOperationsBuilder pendingInputBuilder = null;
|
||||
|
||||
PgpSignEncryptData data = input.getData();
|
||||
// if signing subkey has not explicitly been set, get first usable subkey capable of signing
|
||||
if (data.getSignatureMasterKeyId() != Constants.key.none
|
||||
&& data.getSignatureSubKeyId() == null) {
|
||||
try {
|
||||
long signKeyId = mKeyRepository.getCachedPublicKeyRing(
|
||||
data.getSignatureMasterKeyId()).getSecretSignId();
|
||||
data.setSignatureSubKeyId(signKeyId);
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
Log.e(Constants.TAG, "Key not found", e);
|
||||
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
if (checkCancelled()) {
|
||||
log.add(LogType.MSG_OPERATION_CANCELLED, 0);
|
||||
@@ -98,13 +81,14 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
|
||||
|
||||
PgpSignEncryptOperation op = new PgpSignEncryptOperation(mContext, mKeyRepository,
|
||||
new ProgressScaler(mProgressable, 100 * count / total, 100 * ++count / total, 100), mCancelled);
|
||||
PgpSignEncryptInputParcel inputParcel = new PgpSignEncryptInputParcel(input.getData());
|
||||
PgpSignEncryptInputParcel inputParcel;
|
||||
if (inputBytes != null) {
|
||||
inputParcel.setInputBytes(inputBytes);
|
||||
inputParcel = PgpSignEncryptInputParcel.createForBytes(
|
||||
input.getSignEncryptData(), outputUris.pollFirst(), inputBytes);
|
||||
} else {
|
||||
inputParcel.setInputUri(inputUris.removeFirst());
|
||||
inputParcel = PgpSignEncryptInputParcel.createForInputUri(
|
||||
input.getSignEncryptData(), outputUris.pollFirst(), inputUris.removeFirst());
|
||||
}
|
||||
inputParcel.setOutputUri(outputUris.pollFirst());
|
||||
|
||||
PgpSignEncryptResult result = op.execute(inputParcel, cryptoInput);
|
||||
results.add(result);
|
||||
@@ -118,7 +102,7 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
|
||||
}
|
||||
if (pendingInputBuilder == null) {
|
||||
pendingInputBuilder = new SecurityTokenSignOperationsBuilder(requiredInput.mSignatureTime,
|
||||
data.getSignatureMasterKeyId(), data.getSignatureSubKeyId());
|
||||
requiredInput.getMasterKeyId(), requiredInput.getSubKeyId());
|
||||
}
|
||||
pendingInputBuilder.addAll(requiredInput);
|
||||
} else if (!result.success()) {
|
||||
|
||||
@@ -96,7 +96,7 @@ public class UploadOperation extends BaseOperation<UploadKeyringParcel> {
|
||||
|
||||
ParcelableHkpKeyserver hkpKeyserver;
|
||||
{
|
||||
hkpKeyserver = uploadInput.mKeyserver;
|
||||
hkpKeyserver = uploadInput.getKeyserver();
|
||||
log.add(LogType.MSG_UPLOAD_SERVER, 1, hkpKeyserver.toString());
|
||||
}
|
||||
|
||||
@@ -110,22 +110,15 @@ public class UploadOperation extends BaseOperation<UploadKeyringParcel> {
|
||||
|
||||
@Nullable
|
||||
private CanonicalizedPublicKeyRing getPublicKeyringFromInput(OperationLog log, UploadKeyringParcel uploadInput) {
|
||||
|
||||
boolean hasMasterKeyId = uploadInput.mMasterKeyId != null;
|
||||
boolean hasKeyringBytes = uploadInput.mUncachedKeyringBytes != null;
|
||||
if (hasMasterKeyId == hasKeyringBytes) {
|
||||
throw new IllegalArgumentException("either keyid xor bytes must be non-null for this method call!");
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (hasMasterKeyId) {
|
||||
log.add(LogType.MSG_UPLOAD_KEY, 0, KeyFormattingUtils.convertKeyIdToHex(uploadInput.mMasterKeyId));
|
||||
return mKeyRepository.getCanonicalizedPublicKeyRing(uploadInput.mMasterKeyId);
|
||||
Long masterKeyId = uploadInput.getMasterKeyId();
|
||||
if (masterKeyId != null) {
|
||||
log.add(LogType.MSG_UPLOAD_KEY, 0, KeyFormattingUtils.convertKeyIdToHex(masterKeyId));
|
||||
return mKeyRepository.getCanonicalizedPublicKeyRing(masterKeyId);
|
||||
}
|
||||
|
||||
CanonicalizedKeyRing canonicalizedRing =
|
||||
UncachedKeyRing.decodeFromData(uploadInput.mUncachedKeyringBytes)
|
||||
UncachedKeyRing.decodeFromData(uploadInput.getUncachedKeyringBytes())
|
||||
.canonicalize(new OperationLog(), 0, true);
|
||||
if (!CanonicalizedPublicKeyRing.class.isInstance(canonicalizedRing)) {
|
||||
throw new IllegalArgumentException("keyring bytes must contain public key ring!");
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import org.bouncycastle.bcpg.S2K;
|
||||
|
||||
|
||||
/** This is an immutable and parcelable class which stores the full s2k parametrization
|
||||
* of an encrypted secret key, i.e. all fields of the {@link S2K} class (type, hash algo,
|
||||
* iteration count, iv) plus the encryptionAlgorithm. This class is intended to be used
|
||||
* as key in a HashMap for session key caching purposes, and overrides the
|
||||
* {@link #hashCode} and {@link #equals} methods in a suitable way.
|
||||
*
|
||||
* Note that although it is a rather unlikely scenario that secret keys of the same key
|
||||
* are encrypted with different ciphers, the encryption algorithm still determines the
|
||||
* length of the specific session key and thus needs to be considered for purposes of
|
||||
* session key caching.
|
||||
*
|
||||
* @see org.bouncycastle.bcpg.S2K
|
||||
*/
|
||||
public class ComparableS2K implements Parcelable {
|
||||
|
||||
private final int encryptionAlgorithm;
|
||||
private final int s2kType;
|
||||
private final int s2kHashAlgo;
|
||||
private final long s2kItCount;
|
||||
private final byte[] s2kIV;
|
||||
|
||||
Integer cachedHashCode;
|
||||
|
||||
public ComparableS2K(int encryptionAlgorithm, S2K s2k) {
|
||||
this.encryptionAlgorithm = encryptionAlgorithm;
|
||||
this.s2kType = s2k.getType();
|
||||
this.s2kHashAlgo = s2k.getHashAlgorithm();
|
||||
this.s2kItCount = s2k.getIterationCount();
|
||||
this.s2kIV = s2k.getIV();
|
||||
}
|
||||
|
||||
protected ComparableS2K(Parcel in) {
|
||||
encryptionAlgorithm = in.readInt();
|
||||
s2kType = in.readInt();
|
||||
s2kHashAlgo = in.readInt();
|
||||
s2kItCount = in.readLong();
|
||||
s2kIV = in.createByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (cachedHashCode == null) {
|
||||
cachedHashCode = encryptionAlgorithm;
|
||||
cachedHashCode = 31 * cachedHashCode + s2kType;
|
||||
cachedHashCode = 31 * cachedHashCode + s2kHashAlgo;
|
||||
cachedHashCode = 31 * cachedHashCode + (int) (s2kItCount ^ (s2kItCount >>> 32));
|
||||
cachedHashCode = 31 * cachedHashCode + Arrays.hashCode(s2kIV);
|
||||
}
|
||||
|
||||
return cachedHashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
boolean isComparableS2K = o instanceof ComparableS2K;
|
||||
if (!isComparableS2K) {
|
||||
return false;
|
||||
}
|
||||
ComparableS2K other = (ComparableS2K) o;
|
||||
return encryptionAlgorithm == other.encryptionAlgorithm
|
||||
&& s2kType == other.s2kType
|
||||
&& s2kHashAlgo == other.s2kHashAlgo
|
||||
&& s2kItCount == other.s2kItCount
|
||||
&& Arrays.equals(s2kIV, other.s2kIV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(encryptionAlgorithm);
|
||||
dest.writeInt(s2kType);
|
||||
dest.writeInt(s2kHashAlgo);
|
||||
dest.writeLong(s2kItCount);
|
||||
dest.writeByteArray(s2kIV);
|
||||
}
|
||||
|
||||
public static final Creator<ComparableS2K> CREATOR = new Creator<ComparableS2K>() {
|
||||
@Override
|
||||
public ComparableS2K createFromParcel(Parcel in) {
|
||||
return new ComparableS2K(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComparableS2K[] newArray(int size) {
|
||||
return new ComparableS2K[size];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.auto.value.extension.memoized.Memoized;
|
||||
import org.bouncycastle.bcpg.S2K;
|
||||
|
||||
|
||||
/** This is an immutable and parcelable class which stores the full s2k parametrization
|
||||
* of an encrypted secret key, i.e. all fields of the {@link S2K} class (type, hash algo,
|
||||
* iteration count, iv) plus the encryptionAlgorithm. This class is intended to be used
|
||||
* as key in a HashMap for session key caching purposes, and overrides the
|
||||
* {@link #hashCode} and {@link #equals} methods in a suitable way.
|
||||
*
|
||||
* Note that although it is a rather unlikely scenario that secret keys of the same key
|
||||
* are encrypted with different ciphers, the encryption algorithm still determines the
|
||||
* length of the specific session key and thus needs to be considered for purposes of
|
||||
* session key caching.
|
||||
*
|
||||
* @see org.bouncycastle.bcpg.S2K
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class ParcelableS2K implements Parcelable {
|
||||
abstract int getEncryptionAlgorithm();
|
||||
abstract int getS2kType();
|
||||
abstract int getS2kHashAlgo();
|
||||
abstract long getS2kItCount();
|
||||
@SuppressWarnings("mutable")
|
||||
abstract byte[] getS2kIV();
|
||||
|
||||
@Memoized
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
public static ParcelableS2K fromS2K(int encryptionAlgorithm, S2K s2k) {
|
||||
return new AutoValue_ParcelableS2K(encryptionAlgorithm,
|
||||
s2k.getType(), s2k.getHashAlgorithm(), s2k.getIterationCount(), s2k.getIV());
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -80,12 +81,13 @@ public class PgpCertifyOperation {
|
||||
publicKey.getKeyID(), publicKey.getKeyID());
|
||||
|
||||
try {
|
||||
if (action.mUserIds != null) {
|
||||
log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(),
|
||||
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
|
||||
ArrayList<String> userIds = action.getUserIds();
|
||||
if (userIds != null && !userIds.isEmpty()) {
|
||||
log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, userIds.size(),
|
||||
KeyFormattingUtils.convertKeyIdToHex(action.getMasterKeyId()));
|
||||
|
||||
// fetch public key ring, add the certification and return it
|
||||
for (String userId : action.mUserIds) {
|
||||
for (String userId : userIds) {
|
||||
try {
|
||||
PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
|
||||
publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
|
||||
@@ -96,12 +98,13 @@ public class PgpCertifyOperation {
|
||||
|
||||
}
|
||||
|
||||
if (action.mUserAttributes != null) {
|
||||
log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, action.mUserAttributes.size(),
|
||||
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
|
||||
ArrayList<WrappedUserAttribute> userAttributes = action.getUserAttributes();
|
||||
if (userAttributes != null && !userAttributes.isEmpty()) {
|
||||
log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, userAttributes.size(),
|
||||
KeyFormattingUtils.convertKeyIdToHex(action.getMasterKeyId()));
|
||||
|
||||
// fetch public key ring, add the certification and return it
|
||||
for (WrappedUserAttribute userAttribute : action.mUserAttributes) {
|
||||
for (WrappedUserAttribute userAttribute : userAttributes) {
|
||||
PGPUserAttributeSubpacketVector vector = userAttribute.getVector();
|
||||
try {
|
||||
PGPSignature sig = signatureGenerator.generateCertification(vector, publicKey);
|
||||
|
||||
@@ -19,152 +19,69 @@
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class PgpDecryptVerifyInputParcel implements Parcelable {
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
private Uri mInputUri;
|
||||
private Uri mOutputUri;
|
||||
private byte[] mInputBytes;
|
||||
|
||||
private boolean mAllowSymmetricDecryption;
|
||||
private HashSet<Long> mAllowedKeyIds;
|
||||
private boolean mDecryptMetadataOnly;
|
||||
private byte[] mDetachedSignature;
|
||||
private String mRequiredSignerFingerprint;
|
||||
private String mSenderAddress;
|
||||
@AutoValue
|
||||
public abstract class PgpDecryptVerifyInputParcel implements Parcelable {
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
abstract byte[] getInputBytes();
|
||||
|
||||
public PgpDecryptVerifyInputParcel() {
|
||||
@Nullable
|
||||
abstract Uri getInputUri();
|
||||
@Nullable
|
||||
abstract Uri getOutputUri();
|
||||
|
||||
abstract boolean isAllowSymmetricDecryption();
|
||||
abstract boolean isDecryptMetadataOnly();
|
||||
|
||||
@Nullable
|
||||
abstract List<Long> getAllowedKeyIds();
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
abstract byte[] getDetachedSignature();
|
||||
@Nullable
|
||||
abstract String getSenderAddress();
|
||||
|
||||
public abstract Builder toBuilder();
|
||||
|
||||
public static Builder builder() {
|
||||
return new AutoValue_PgpDecryptVerifyInputParcel.Builder()
|
||||
.setAllowSymmetricDecryption(false)
|
||||
.setDecryptMetadataOnly(false);
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel(Uri inputUri, Uri outputUri) {
|
||||
mInputUri = inputUri;
|
||||
mOutputUri = outputUri;
|
||||
}
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
public abstract Builder setInputBytes(byte[] inputBytes);
|
||||
public abstract Builder setInputUri(Uri inputUri);
|
||||
public abstract Builder setOutputUri(Uri outputUri);
|
||||
|
||||
public PgpDecryptVerifyInputParcel(byte[] inputBytes) {
|
||||
mInputBytes = inputBytes;
|
||||
}
|
||||
public abstract Builder setAllowSymmetricDecryption(boolean allowSymmetricDecryption);
|
||||
public abstract Builder setDecryptMetadataOnly(boolean decryptMetadataOnly);
|
||||
public abstract Builder setDetachedSignature(byte[] detachedSignature);
|
||||
public abstract Builder setSenderAddress(String senderAddress);
|
||||
|
||||
PgpDecryptVerifyInputParcel(Parcel source) {
|
||||
// we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
|
||||
mInputUri = source.readParcelable(getClass().getClassLoader());
|
||||
mOutputUri = source.readParcelable(getClass().getClassLoader());
|
||||
mInputBytes = source.createByteArray();
|
||||
public abstract Builder setAllowedKeyIds(List<Long> allowedKeyIds);
|
||||
abstract List<Long> getAllowedKeyIds();
|
||||
|
||||
mAllowSymmetricDecryption = source.readInt() != 0;
|
||||
mAllowedKeyIds = (HashSet<Long>) source.readSerializable();
|
||||
mDecryptMetadataOnly = source.readInt() != 0;
|
||||
mDetachedSignature = source.createByteArray();
|
||||
mRequiredSignerFingerprint = source.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(mInputUri, 0);
|
||||
dest.writeParcelable(mOutputUri, 0);
|
||||
dest.writeByteArray(mInputBytes);
|
||||
|
||||
dest.writeInt(mAllowSymmetricDecryption ? 1 : 0);
|
||||
dest.writeSerializable(mAllowedKeyIds);
|
||||
dest.writeInt(mDecryptMetadataOnly ? 1 : 0);
|
||||
dest.writeByteArray(mDetachedSignature);
|
||||
dest.writeString(mRequiredSignerFingerprint);
|
||||
}
|
||||
|
||||
byte[] getInputBytes() {
|
||||
return mInputBytes;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel setInputUri(Uri uri) {
|
||||
mInputUri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
Uri getInputUri() {
|
||||
return mInputUri;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel setOutputUri(Uri uri) {
|
||||
mOutputUri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
Uri getOutputUri() {
|
||||
return mOutputUri;
|
||||
}
|
||||
|
||||
boolean isAllowSymmetricDecryption() {
|
||||
return mAllowSymmetricDecryption;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel setAllowSymmetricDecryption(boolean allowSymmetricDecryption) {
|
||||
mAllowSymmetricDecryption = allowSymmetricDecryption;
|
||||
return this;
|
||||
}
|
||||
|
||||
HashSet<Long> getAllowedKeyIds() {
|
||||
return mAllowedKeyIds;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel setAllowedKeyIds(HashSet<Long> allowedKeyIds) {
|
||||
mAllowedKeyIds = allowedKeyIds;
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean isDecryptMetadataOnly() {
|
||||
return mDecryptMetadataOnly;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel setDecryptMetadataOnly(boolean decryptMetadataOnly) {
|
||||
mDecryptMetadataOnly = decryptMetadataOnly;
|
||||
return this;
|
||||
}
|
||||
|
||||
byte[] getDetachedSignature() {
|
||||
return mDetachedSignature;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel setDetachedSignature(byte[] detachedSignature) {
|
||||
mDetachedSignature = detachedSignature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel setSenderAddress(String senderAddress) {
|
||||
mSenderAddress = senderAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSenderAddress() {
|
||||
return mSenderAddress;
|
||||
}
|
||||
|
||||
String getRequiredSignerFingerprint() {
|
||||
return mRequiredSignerFingerprint;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel setRequiredSignerFingerprint(String requiredSignerFingerprint) {
|
||||
mRequiredSignerFingerprint = requiredSignerFingerprint;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static final Creator<PgpDecryptVerifyInputParcel> CREATOR = new Creator<PgpDecryptVerifyInputParcel>() {
|
||||
public PgpDecryptVerifyInputParcel createFromParcel(final Parcel source) {
|
||||
return new PgpDecryptVerifyInputParcel(source);
|
||||
abstract PgpDecryptVerifyInputParcel autoBuild();
|
||||
public PgpDecryptVerifyInputParcel build() {
|
||||
List<Long> allowedKeyIds = getAllowedKeyIds();
|
||||
if (allowedKeyIds != null) {
|
||||
setAllowedKeyIds(Collections.unmodifiableList(allowedKeyIds));
|
||||
}
|
||||
return autoBuild();
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel[] newArray(final int size) {
|
||||
return new PgpDecryptVerifyInputParcel[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,10 +69,9 @@ 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.DecryptVerifySecurityProblem.DecryptVerifySecurityProblemBuilder;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.MissingMdc;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
@@ -321,6 +320,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
decryptionResultBuilder.setEncrypted(true);
|
||||
if (esResult.sessionKey != null && esResult.decryptedSessionKey != null) {
|
||||
decryptionResultBuilder.setSessionKey(esResult.sessionKey, esResult.decryptedSessionKey);
|
||||
cryptoInput = cryptoInput.withCryptoData(esResult.sessionKey, esResult.decryptedSessionKey);
|
||||
}
|
||||
|
||||
if (esResult.encryptionKeySecurityProblem != null) {
|
||||
@@ -361,10 +361,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
log.add(LogType.MSG_DC_CLEAR_DECOMPRESS, indent + 1);
|
||||
|
||||
PGPCompressedData compressedData = (PGPCompressedData) dataChunk;
|
||||
|
||||
JcaSkipMarkerPGPObjectFactory fact = new JcaSkipMarkerPGPObjectFactory(compressedData.getDataStream());
|
||||
dataChunk = fact.nextObject();
|
||||
plainFact = fact;
|
||||
plainFact = new JcaSkipMarkerPGPObjectFactory(compressedData.getDataStream());
|
||||
dataChunk = plainFact.nextObject();
|
||||
}
|
||||
|
||||
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(
|
||||
@@ -378,10 +376,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
dataChunk = plainFact.nextObject();
|
||||
}
|
||||
|
||||
OpenPgpMetadata metadata;
|
||||
|
||||
if ( ! (dataChunk instanceof PGPLiteralData)) {
|
||||
|
||||
if (!(dataChunk instanceof PGPLiteralData)) {
|
||||
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, indent);
|
||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
||||
|
||||
@@ -422,6 +417,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
log.add(LogType.MSG_DC_CLEAR_META_TIME, indent + 1,
|
||||
new Date(literalData.getModificationTime().getTime()).toString());
|
||||
|
||||
OpenPgpMetadata metadata;
|
||||
|
||||
// return here if we want to decrypt the metadata only
|
||||
if (input.isDecryptMetadataOnly()) {
|
||||
|
||||
@@ -820,7 +817,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
result.encryptedData = encryptedDataAsymmetric;
|
||||
|
||||
Map<ByteBuffer, byte[]> cachedSessionKeys = decryptorFactory.getCachedSessionKeys();
|
||||
cryptoInput.addCryptoData(cachedSessionKeys);
|
||||
if (cachedSessionKeys.size() >= 1) {
|
||||
Entry<ByteBuffer, byte[]> entry = cachedSessionKeys.entrySet().iterator().next();
|
||||
result.sessionKey = entry.getKey().array();
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.security.spec.ECGenParameterSpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@@ -79,8 +80,10 @@ import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
|
||||
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Builder;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenKeyToCardOperationsBuilder;
|
||||
@@ -166,17 +169,17 @@ public class PgpKeyOperation {
|
||||
|
||||
try {
|
||||
// Some safety checks
|
||||
if (add.mAlgorithm == Algorithm.ECDH || add.mAlgorithm == Algorithm.ECDSA) {
|
||||
if (add.mCurve == null) {
|
||||
if (add.getAlgorithm() == Algorithm.ECDH || add.getAlgorithm() == Algorithm.ECDSA) {
|
||||
if (add.getCurve() == null) {
|
||||
log.add(LogType.MSG_CR_ERROR_NO_CURVE, indent);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (add.mKeySize == null) {
|
||||
if (add.getKeySize() == null) {
|
||||
log.add(LogType.MSG_CR_ERROR_NO_KEYSIZE, indent);
|
||||
return null;
|
||||
}
|
||||
if (add.mKeySize < 2048) {
|
||||
if (add.getKeySize() < 2048) {
|
||||
log.add(LogType.MSG_CR_ERROR_KEYSIZE_2048, indent);
|
||||
return null;
|
||||
}
|
||||
@@ -185,27 +188,27 @@ public class PgpKeyOperation {
|
||||
int algorithm;
|
||||
KeyPairGenerator keyGen;
|
||||
|
||||
switch (add.mAlgorithm) {
|
||||
switch (add.getAlgorithm()) {
|
||||
case DSA: {
|
||||
if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
|
||||
if ((add.getFlags() & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
|
||||
log.add(LogType.MSG_CR_ERROR_FLAGS_DSA, indent);
|
||||
return null;
|
||||
}
|
||||
progress(R.string.progress_generating_dsa, 30);
|
||||
keyGen = KeyPairGenerator.getInstance("DSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
keyGen.initialize(add.mKeySize, new SecureRandom());
|
||||
keyGen.initialize(add.getKeySize(), new SecureRandom());
|
||||
algorithm = PGPPublicKey.DSA;
|
||||
break;
|
||||
}
|
||||
|
||||
case ELGAMAL: {
|
||||
if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
|
||||
if ((add.getFlags() & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
|
||||
log.add(LogType.MSG_CR_ERROR_FLAGS_ELGAMAL, indent);
|
||||
return null;
|
||||
}
|
||||
progress(R.string.progress_generating_elgamal, 30);
|
||||
keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
BigInteger p = Primes.getBestPrime(add.mKeySize);
|
||||
BigInteger p = Primes.getBestPrime(add.getKeySize());
|
||||
BigInteger g = new BigInteger("2");
|
||||
|
||||
ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g);
|
||||
@@ -218,19 +221,19 @@ public class PgpKeyOperation {
|
||||
case RSA: {
|
||||
progress(R.string.progress_generating_rsa, 30);
|
||||
keyGen = KeyPairGenerator.getInstance("RSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
keyGen.initialize(add.mKeySize, new SecureRandom());
|
||||
keyGen.initialize(add.getKeySize(), new SecureRandom());
|
||||
|
||||
algorithm = PGPPublicKey.RSA_GENERAL;
|
||||
break;
|
||||
}
|
||||
|
||||
case ECDSA: {
|
||||
if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
|
||||
if ((add.getFlags() & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
|
||||
log.add(LogType.MSG_CR_ERROR_FLAGS_ECDSA, indent);
|
||||
return null;
|
||||
}
|
||||
progress(R.string.progress_generating_ecdsa, 30);
|
||||
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve);
|
||||
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.getCurve());
|
||||
keyGen = KeyPairGenerator.getInstance("ECDSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
keyGen.initialize(ecParamSpec, new SecureRandom());
|
||||
|
||||
@@ -240,12 +243,12 @@ public class PgpKeyOperation {
|
||||
|
||||
case ECDH: {
|
||||
// make sure there are no sign or certify flags set
|
||||
if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
|
||||
if ((add.getFlags() & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
|
||||
log.add(LogType.MSG_CR_ERROR_FLAGS_ECDH, indent);
|
||||
return null;
|
||||
}
|
||||
progress(R.string.progress_generating_ecdh, 30);
|
||||
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve);
|
||||
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.getCurve());
|
||||
keyGen = KeyPairGenerator.getInstance("ECDH", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
keyGen.initialize(ecParamSpec, new SecureRandom());
|
||||
|
||||
@@ -285,23 +288,23 @@ public class PgpKeyOperation {
|
||||
progress(R.string.progress_building_key, 0);
|
||||
indent += 1;
|
||||
|
||||
if (saveParcel.mAddSubKeys.isEmpty()) {
|
||||
if (saveParcel.getAddSubKeys().isEmpty()) {
|
||||
log.add(LogType.MSG_CR_ERROR_NO_MASTER, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
if (saveParcel.mAddUserIds.isEmpty()) {
|
||||
if (saveParcel.getAddUserIds().isEmpty()) {
|
||||
log.add(LogType.MSG_CR_ERROR_NO_USER_ID, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
SubkeyAdd add = saveParcel.mAddSubKeys.remove(0);
|
||||
if ((add.mFlags & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
|
||||
SubkeyAdd certificationKey = saveParcel.getAddSubKeys().get(0);
|
||||
if ((certificationKey.getFlags() & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
|
||||
log.add(LogType.MSG_CR_ERROR_NO_CERTIFY, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
if (add.mExpiry == null) {
|
||||
if (certificationKey.getExpiry() == null) {
|
||||
log.add(LogType.MSG_CR_ERROR_NULL_EXPIRY, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
@@ -309,7 +312,7 @@ public class PgpKeyOperation {
|
||||
Date creationTime = new Date();
|
||||
|
||||
subProgressPush(10, 30);
|
||||
PGPKeyPair keyPair = createKey(add, creationTime, log, indent);
|
||||
PGPKeyPair keyPair = createKey(certificationKey, creationTime, log, indent);
|
||||
subProgressPop();
|
||||
|
||||
// return null if this failed (an error will already have been logged by createKey)
|
||||
@@ -335,9 +338,14 @@ public class PgpKeyOperation {
|
||||
PGPSecretKeyRing sKR = new PGPSecretKeyRing(
|
||||
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
|
||||
|
||||
// Remove certification key from remaining SaveKeyringParcel
|
||||
Builder builder = SaveKeyringParcel.buildUpon(saveParcel);
|
||||
builder.getMutableAddSubKeys().remove(certificationKey);
|
||||
saveParcel = builder.build();
|
||||
|
||||
subProgressPush(50, 100);
|
||||
CryptoInputParcel cryptoInput = new CryptoInputParcel(creationTime, new Passphrase(""));
|
||||
return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, cryptoInput, saveParcel, log, indent);
|
||||
CryptoInputParcel cryptoInput = CryptoInputParcel.createCryptoInputParcel(creationTime, new Passphrase(""));
|
||||
return internal(sKR, masterSecretKey, certificationKey.getFlags(), certificationKey.getExpiry(), cryptoInput, saveParcel, log, indent);
|
||||
|
||||
} catch (PGPException e) {
|
||||
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
|
||||
@@ -392,7 +400,7 @@ public class PgpKeyOperation {
|
||||
progress(R.string.progress_building_key, 0);
|
||||
|
||||
// Make sure this is called with a proper SaveKeyringParcel
|
||||
if (saveParcel.mMasterKeyId == null || saveParcel.mMasterKeyId != wsKR.getMasterKeyId()) {
|
||||
if (saveParcel.getMasterKeyId() == null || saveParcel.getMasterKeyId() != wsKR.getMasterKeyId()) {
|
||||
log.add(LogType.MSG_MF_ERROR_KEYID, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
@@ -402,75 +410,29 @@ public class PgpKeyOperation {
|
||||
PGPSecretKey masterSecretKey = sKR.getSecretKey();
|
||||
|
||||
// Make sure the fingerprint matches
|
||||
if (saveParcel.mFingerprint == null || !Arrays.equals(saveParcel.mFingerprint,
|
||||
if (saveParcel.getFingerprint() == null || !Arrays.equals(saveParcel.getFingerprint(),
|
||||
masterSecretKey.getPublicKey().getFingerprint())) {
|
||||
log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
if (saveParcel.isEmpty()) {
|
||||
if (isParcelEmpty(saveParcel)) {
|
||||
log.add(LogType.MSG_MF_ERROR_NOOP, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
// Ensure we don't have multiple keys for the same slot.
|
||||
boolean hasSign = false;
|
||||
boolean hasEncrypt = false;
|
||||
boolean hasAuth = false;
|
||||
for(SaveKeyringParcel.SubkeyChange change : saveParcel.mChangeSubKeys) {
|
||||
if (change.mMoveKeyToSecurityToken) {
|
||||
// If this is a moveKeyToSecurityToken operation, see if it was completed: look for a hash
|
||||
// matching the given subkey ID in cryptoData.
|
||||
byte[] subKeyId = new byte[8];
|
||||
ByteBuffer buf = ByteBuffer.wrap(subKeyId);
|
||||
buf.putLong(change.mKeyId).rewind();
|
||||
saveParcel = parseSecurityTokenSerialNumberIntoSubkeyChanges(cryptoInput, saveParcel);
|
||||
|
||||
byte[] serialNumber = cryptoInput.getCryptoData().get(buf);
|
||||
if (serialNumber != null) {
|
||||
change.mMoveKeyToSecurityToken = false;
|
||||
change.mSecurityTokenSerialNo = serialNumber;
|
||||
}
|
||||
}
|
||||
|
||||
if (change.mMoveKeyToSecurityToken) {
|
||||
// Pending moveKeyToSecurityToken operation. Need to make sure that we don't have multiple
|
||||
// subkeys pending for the same slot.
|
||||
CanonicalizedSecretKey wsK = wsKR.getSecretKey(change.mKeyId);
|
||||
|
||||
if ((wsK.canSign() || wsK.canCertify())) {
|
||||
if (hasSign) {
|
||||
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
} else {
|
||||
hasSign = true;
|
||||
}
|
||||
} else if ((wsK.canEncrypt())) {
|
||||
if (hasEncrypt) {
|
||||
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
} else {
|
||||
hasEncrypt = true;
|
||||
}
|
||||
} else if ((wsK.canAuthenticate())) {
|
||||
if (hasAuth) {
|
||||
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
} else {
|
||||
hasAuth = true;
|
||||
}
|
||||
} else {
|
||||
log.add(LogType.MSG_MF_ERROR_INVALID_FLAGS_FOR_KEYTOCARD, indent + 1);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
}
|
||||
if (!checkCapabilitiesAreUnique(wsKR, saveParcel, log, indent)) {
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
if (isDummy(masterSecretKey) && ! saveParcel.isRestrictedOnly()) {
|
||||
if (isDummy(masterSecretKey) && ! isParcelRestrictedOnly(saveParcel)) {
|
||||
log.add(LogType.MSG_EK_ERROR_DUMMY, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
if (isDummy(masterSecretKey) || saveParcel.isRestrictedOnly()) {
|
||||
if (isDummy(masterSecretKey) || isParcelRestrictedOnly(saveParcel)) {
|
||||
log.add(LogType.MSG_MF_RESTRICTED_MODE, indent);
|
||||
return internalRestricted(sKR, saveParcel, log, indent + 1);
|
||||
}
|
||||
@@ -494,6 +456,70 @@ public class PgpKeyOperation {
|
||||
|
||||
}
|
||||
|
||||
private SaveKeyringParcel parseSecurityTokenSerialNumberIntoSubkeyChanges(CryptoInputParcel cryptoInput,
|
||||
SaveKeyringParcel saveParcel) {
|
||||
SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildUpon(saveParcel);
|
||||
for (SubkeyChange change : saveParcel.getChangeSubKeys()) {
|
||||
if (change.getMoveKeyToSecurityToken()) {
|
||||
// If this is a moveKeyToSecurityToken operation, see if it was completed: look for a hash
|
||||
// matching the given subkey ID in cryptoData.
|
||||
byte[] subKeyId = new byte[8];
|
||||
ByteBuffer buf = ByteBuffer.wrap(subKeyId);
|
||||
buf.putLong(change.getSubKeyId()).rewind();
|
||||
|
||||
byte[] serialNumber = cryptoInput.getCryptoData().get(buf);
|
||||
if (serialNumber != null) {
|
||||
builder.addOrReplaceSubkeyChange(
|
||||
SubkeyChange.createSecurityTokenSerialNo(change.getSubKeyId(), serialNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
saveParcel = builder.build();
|
||||
return saveParcel;
|
||||
}
|
||||
|
||||
private boolean checkCapabilitiesAreUnique(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel,
|
||||
OperationLog log, int indent) {
|
||||
boolean hasSign = false;
|
||||
boolean hasEncrypt = false;
|
||||
boolean hasAuth = false;
|
||||
|
||||
for (SubkeyChange change : saveParcel.getChangeSubKeys()) {
|
||||
if (change.getMoveKeyToSecurityToken()) {
|
||||
// Pending moveKeyToSecurityToken operation. Need to make sure that we don't have multiple
|
||||
// subkeys pending for the same slot.
|
||||
CanonicalizedSecretKey wsK = wsKR.getSecretKey(change.getSubKeyId());
|
||||
|
||||
if ((wsK.canSign() || wsK.canCertify())) {
|
||||
if (hasSign) {
|
||||
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
|
||||
return false;
|
||||
} else {
|
||||
hasSign = true;
|
||||
}
|
||||
} else if ((wsK.canEncrypt())) {
|
||||
if (hasEncrypt) {
|
||||
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
|
||||
return false;
|
||||
} else {
|
||||
hasEncrypt = true;
|
||||
}
|
||||
} else if ((wsK.canAuthenticate())) {
|
||||
if (hasAuth) {
|
||||
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
|
||||
return false;
|
||||
} else {
|
||||
hasAuth = true;
|
||||
}
|
||||
} else {
|
||||
log.add(LogType.MSG_MF_ERROR_INVALID_FLAGS_FOR_KEYTOCARD, indent + 1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
|
||||
int masterKeyFlags, long masterKeyExpiry,
|
||||
CryptoInputParcel cryptoInput,
|
||||
@@ -547,10 +573,11 @@ public class PgpKeyOperation {
|
||||
|
||||
// 2a. Add certificates for new user ids
|
||||
subProgressPush(15, 23);
|
||||
for (int i = 0; i < saveParcel.mAddUserIds.size(); i++) {
|
||||
String changePrimaryUserId = saveParcel.getChangePrimaryUserId();
|
||||
for (int i = 0; i < saveParcel.getAddUserIds().size(); i++) {
|
||||
|
||||
progress(R.string.progress_modify_adduid, (i - 1) * (100 / saveParcel.mAddUserIds.size()));
|
||||
String userId = saveParcel.mAddUserIds.get(i);
|
||||
progress(R.string.progress_modify_adduid, (i - 1) * (100 / saveParcel.getAddUserIds().size()));
|
||||
String userId = saveParcel.getAddUserIds().get(i);
|
||||
log.add(LogType.MSG_MF_UID_ADD, indent, userId);
|
||||
|
||||
if ("".equals(userId)) {
|
||||
@@ -581,8 +608,8 @@ public class PgpKeyOperation {
|
||||
}
|
||||
|
||||
// if it's supposed to be primary, we can do that here as well
|
||||
boolean isPrimary = saveParcel.mChangePrimaryUserId != null
|
||||
&& userId.equals(saveParcel.mChangePrimaryUserId);
|
||||
boolean isPrimary = changePrimaryUserId != null
|
||||
&& userId.equals(changePrimaryUserId);
|
||||
// generate and add new certificate
|
||||
try {
|
||||
PGPSignature cert = generateUserIdSignature(
|
||||
@@ -599,10 +626,10 @@ public class PgpKeyOperation {
|
||||
|
||||
// 2b. Add certificates for new user ids
|
||||
subProgressPush(23, 32);
|
||||
for (int i = 0; i < saveParcel.mAddUserAttribute.size(); i++) {
|
||||
|
||||
progress(R.string.progress_modify_adduat, (i - 1) * (100 / saveParcel.mAddUserAttribute.size()));
|
||||
WrappedUserAttribute attribute = saveParcel.mAddUserAttribute.get(i);
|
||||
List<WrappedUserAttribute> addUserAttributes = saveParcel.getAddUserAttribute();
|
||||
for (int i = 0; i < addUserAttributes.size(); i++) {
|
||||
progress(R.string.progress_modify_adduat, (i - 1) * (100 / addUserAttributes.size()));
|
||||
WrappedUserAttribute attribute = addUserAttributes.get(i);
|
||||
|
||||
switch (attribute.getType()) {
|
||||
// the 'none' type must not succeed
|
||||
@@ -635,10 +662,10 @@ public class PgpKeyOperation {
|
||||
|
||||
// 2c. Add revocations for revoked user ids
|
||||
subProgressPush(32, 40);
|
||||
for (int i = 0; i < saveParcel.mRevokeUserIds.size(); i++) {
|
||||
|
||||
progress(R.string.progress_modify_revokeuid, (i - 1) * (100 / saveParcel.mRevokeUserIds.size()));
|
||||
String userId = saveParcel.mRevokeUserIds.get(i);
|
||||
List<String> revokeUserIds = saveParcel.getRevokeUserIds();
|
||||
for (int i = 0, j = revokeUserIds.size(); i < j; i++) {
|
||||
progress(R.string.progress_modify_revokeuid, (i - 1) * (100 / revokeUserIds.size()));
|
||||
String userId = revokeUserIds.get(i);
|
||||
log.add(LogType.MSG_MF_UID_REVOKE, indent, userId);
|
||||
|
||||
// Make sure the user id exists (yes these are 10 LoC in Java!)
|
||||
@@ -670,12 +697,12 @@ public class PgpKeyOperation {
|
||||
subProgressPop();
|
||||
|
||||
// 3. If primary user id changed, generate new certificates for both old and new
|
||||
if (saveParcel.mChangePrimaryUserId != null) {
|
||||
if (changePrimaryUserId != null) {
|
||||
progress(R.string.progress_modify_primaryuid, 40);
|
||||
|
||||
// keep track if we actually changed one
|
||||
boolean ok = false;
|
||||
log.add(LogType.MSG_MF_UID_PRIMARY, indent, saveParcel.mChangePrimaryUserId);
|
||||
log.add(LogType.MSG_MF_UID_PRIMARY, indent, changePrimaryUserId);
|
||||
indent += 1;
|
||||
|
||||
// we work on the modifiedPublicKey here, to respect new or newly revoked uids
|
||||
@@ -716,7 +743,7 @@ public class PgpKeyOperation {
|
||||
// we definitely should not update certifications of revoked keys, so just leave it.
|
||||
if (isRevoked) {
|
||||
// revoked user ids cannot be primary!
|
||||
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
|
||||
if (userId.equals(changePrimaryUserId)) {
|
||||
log.add(LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
@@ -727,7 +754,7 @@ public class PgpKeyOperation {
|
||||
if (currentCert.getHashedSubPackets() != null
|
||||
&& currentCert.getHashedSubPackets().isPrimaryUserID()) {
|
||||
// if it's the one we want, just leave it as is
|
||||
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
|
||||
if (userId.equals(changePrimaryUserId)) {
|
||||
ok = true;
|
||||
continue;
|
||||
}
|
||||
@@ -753,7 +780,7 @@ public class PgpKeyOperation {
|
||||
// if we are here, this is not currently a primary user id
|
||||
|
||||
// if it should be
|
||||
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
|
||||
if (userId.equals(changePrimaryUserId)) {
|
||||
// add shiny new primary user id certificate
|
||||
log.add(LogType.MSG_MF_PRIMARY_NEW, indent);
|
||||
modifiedPublicKey = PGPPublicKey.removeCertification(
|
||||
@@ -801,67 +828,68 @@ public class PgpKeyOperation {
|
||||
|
||||
// 4a. For each subkey change, generate new subkey binding certificate
|
||||
subProgressPush(50, 60);
|
||||
for (int i = 0; i < saveParcel.mChangeSubKeys.size(); i++) {
|
||||
List<SubkeyChange> changeSubKeys = saveParcel.getChangeSubKeys();
|
||||
for (int i = 0, j = changeSubKeys.size(); i < j; i++) {
|
||||
|
||||
progress(R.string.progress_modify_subkeychange, (i-1) * (100 / saveParcel.mChangeSubKeys.size()));
|
||||
SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i);
|
||||
progress(R.string.progress_modify_subkeychange, (i-1) * (100 / changeSubKeys.size()));
|
||||
SaveKeyringParcel.SubkeyChange change = changeSubKeys.get(i);
|
||||
log.add(LogType.MSG_MF_SUBKEY_CHANGE,
|
||||
indent, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
|
||||
indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
|
||||
|
||||
PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId);
|
||||
PGPSecretKey sKey = sKR.getSecretKey(change.getSubKeyId());
|
||||
if (sKey == null) {
|
||||
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
if (change.mDummyStrip) {
|
||||
if (change.getDummyStrip()) {
|
||||
// IT'S DANGEROUS~
|
||||
// no really, it is. this operation irrevocably removes the private key data from the key
|
||||
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
|
||||
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
|
||||
} else if (change.mMoveKeyToSecurityToken) {
|
||||
} else if (change.getMoveKeyToSecurityToken()) {
|
||||
if (checkSecurityTokenCompatibility(sKey, log, indent + 1)) {
|
||||
log.add(LogType.MSG_MF_KEYTOCARD_START, indent + 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
|
||||
nfcKeyToCardOps.addSubkey(change.mKeyId);
|
||||
KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
|
||||
nfcKeyToCardOps.addSubkey(change.getSubKeyId());
|
||||
} else {
|
||||
// Appropriate log message already set by checkSecurityTokenCompatibility
|
||||
return new PgpEditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
} else if (change.mSecurityTokenSerialNo != null) {
|
||||
} else if (change.getSecurityTokenSerialNo() != null) {
|
||||
// NOTE: Does this code get executed? Or always handled in internalRestricted?
|
||||
if (change.mSecurityTokenSerialNo.length != 16) {
|
||||
if (change.getSecurityTokenSerialNo().length != 16) {
|
||||
log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
log.add(LogType.MSG_MF_KEYTOCARD_FINISH, indent + 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(change.mKeyId),
|
||||
Hex.toHexString(change.mSecurityTokenSerialNo, 8, 6));
|
||||
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.mSecurityTokenSerialNo);
|
||||
KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()),
|
||||
Hex.toHexString(change.getSecurityTokenSerialNo(), 8, 6));
|
||||
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.getSecurityTokenSerialNo());
|
||||
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This doesn't concern us any further
|
||||
if (!change.mRecertify && (change.mExpiry == null && change.mFlags == null)) {
|
||||
if (!change.getRecertify() && (change.getExpiry() == null && change.getFlags() == null)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// expiry must not be in the past
|
||||
if (change.mExpiry != null && change.mExpiry != 0 &&
|
||||
new Date(change.mExpiry*1000).before(new Date())) {
|
||||
if (change.getExpiry() != null && change.getExpiry() != 0 &&
|
||||
new Date(change.getExpiry() * 1000).before(new Date())) {
|
||||
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY,
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
// if this is the master key, update uid certificates instead
|
||||
if (change.mKeyId == masterPublicKey.getKeyID()) {
|
||||
int flags = change.mFlags == null ? masterKeyFlags : change.mFlags;
|
||||
long expiry = change.mExpiry == null ? masterKeyExpiry : change.mExpiry;
|
||||
if (change.getSubKeyId() == masterPublicKey.getKeyID()) {
|
||||
int flags = change.getFlags() == null ? masterKeyFlags : change.getFlags();
|
||||
long expiry = change.getExpiry() == null ? masterKeyExpiry : change.getExpiry();
|
||||
|
||||
if ((flags & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
|
||||
log.add(LogType.MSG_MF_ERROR_NO_CERTIFY, indent + 1);
|
||||
@@ -886,22 +914,22 @@ public class PgpKeyOperation {
|
||||
PGPPublicKey pKey = sKey.getPublicKey();
|
||||
|
||||
// keep old flags, or replace with new ones
|
||||
int flags = change.mFlags == null ? readKeyFlags(pKey) : change.mFlags;
|
||||
int flags = change.getFlags() == null ? readKeyFlags(pKey) : change.getFlags();
|
||||
long expiry;
|
||||
if (change.mExpiry == null) {
|
||||
if (change.getExpiry() == null) {
|
||||
long valid = pKey.getValidSeconds();
|
||||
expiry = valid == 0
|
||||
? 0
|
||||
: pKey.getCreationTime().getTime() / 1000 + pKey.getValidSeconds();
|
||||
} else {
|
||||
expiry = change.mExpiry;
|
||||
expiry = change.getExpiry();
|
||||
}
|
||||
|
||||
// drop all old signatures, they will be superseded by the new one
|
||||
//noinspection unchecked
|
||||
for (PGPSignature sig : new IterableIterator<PGPSignature>(pKey.getSignatures())) {
|
||||
// special case: if there is a revocation, don't use expiry from before
|
||||
if ( (change.mExpiry == null || change.mExpiry == 0L)
|
||||
if ( (change.getExpiry() == null || change.getExpiry() == 0L)
|
||||
&& sig.getSignatureType() == PGPSignature.SUBKEY_REVOCATION) {
|
||||
expiry = 0;
|
||||
}
|
||||
@@ -917,7 +945,7 @@ public class PgpKeyOperation {
|
||||
// super special case: subkey is allowed to sign, but isn't available
|
||||
if (subPrivateKey == null) {
|
||||
log.add(LogType.MSG_MF_ERROR_SUB_STRIPPED,
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
} else {
|
||||
@@ -942,10 +970,10 @@ public class PgpKeyOperation {
|
||||
|
||||
// 4b. For each subkey revocation, generate new subkey revocation certificate
|
||||
subProgressPush(60, 65);
|
||||
for (int i = 0; i < saveParcel.mRevokeSubKeys.size(); i++) {
|
||||
|
||||
progress(R.string.progress_modify_subkeyrevoke, (i-1) * (100 / saveParcel.mRevokeSubKeys.size()));
|
||||
long revocation = saveParcel.mRevokeSubKeys.get(i);
|
||||
List<Long> revokeSubKeys = saveParcel.getRevokeSubKeys();
|
||||
for (int i = 0, j = revokeSubKeys.size(); i < j; i++) {
|
||||
progress(R.string.progress_modify_subkeyrevoke, (i-1) * (100 / revokeSubKeys.size()));
|
||||
long revocation = revokeSubKeys.get(i);
|
||||
log.add(LogType.MSG_MF_SUBKEY_REVOKE,
|
||||
indent, KeyFormattingUtils.convertKeyIdToHex(revocation));
|
||||
|
||||
@@ -974,38 +1002,38 @@ public class PgpKeyOperation {
|
||||
|
||||
// 5. Generate and add new subkeys
|
||||
subProgressPush(70, 90);
|
||||
for (int i = 0; i < saveParcel.mAddSubKeys.size(); i++) {
|
||||
|
||||
List<SubkeyAdd> addSubKeys = saveParcel.getAddSubKeys();
|
||||
for (int i = 0, j = addSubKeys.size(); i < j; i++) {
|
||||
// Check if we were cancelled - again. This operation is expensive so we do it each loop.
|
||||
if (checkCancelled()) {
|
||||
log.add(LogType.MSG_OPERATION_CANCELLED, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null);
|
||||
}
|
||||
|
||||
progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / saveParcel.mAddSubKeys.size()));
|
||||
SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i);
|
||||
progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / addSubKeys.size()));
|
||||
SaveKeyringParcel.SubkeyAdd add = addSubKeys.get(i);
|
||||
log.add(LogType.MSG_MF_SUBKEY_NEW, indent,
|
||||
KeyFormattingUtils.getAlgorithmInfo(add.mAlgorithm, add.mKeySize, add.mCurve) );
|
||||
KeyFormattingUtils.getAlgorithmInfo(add.getAlgorithm(), add.getKeySize(), add.getCurve()) );
|
||||
|
||||
if (isDivertToCard(masterSecretKey)) {
|
||||
log.add(LogType.MSG_MF_ERROR_DIVERT_NEWSUB, indent +1);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
if (add.mExpiry == null) {
|
||||
if (add.getExpiry() == null) {
|
||||
log.add(LogType.MSG_MF_ERROR_NULL_EXPIRY, indent +1);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
if (add.mExpiry > 0L && new Date(add.mExpiry*1000).before(new Date())) {
|
||||
if (add.getExpiry() > 0L && new Date(add.getExpiry() * 1000).before(new Date())) {
|
||||
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY, indent +1);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
// generate a new secret key (privkey only for now)
|
||||
subProgressPush(
|
||||
(i-1) * (100 / saveParcel.mAddSubKeys.size()),
|
||||
i * (100 / saveParcel.mAddSubKeys.size())
|
||||
(i-1) * (100 / addSubKeys.size()),
|
||||
i * (100 / addSubKeys.size())
|
||||
);
|
||||
PGPKeyPair keyPair = createKey(add, cryptoInput.getSignatureTime(), log, indent);
|
||||
subProgressPop();
|
||||
@@ -1022,7 +1050,7 @@ public class PgpKeyOperation {
|
||||
cryptoInput.getSignatureTime(),
|
||||
masterPublicKey, masterPrivateKey,
|
||||
getSignatureGenerator(pKey, cryptoInput, false), keyPair.getPrivateKey(), pKey,
|
||||
add.mFlags, add.mExpiry);
|
||||
add.getFlags(), add.getExpiry());
|
||||
pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
|
||||
} catch (NfcInteractionNeeded e) {
|
||||
nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
|
||||
@@ -1058,13 +1086,13 @@ public class PgpKeyOperation {
|
||||
}
|
||||
|
||||
// 6. If requested, change passphrase
|
||||
if (saveParcel.getChangeUnlockParcel() != null) {
|
||||
if (saveParcel.getNewUnlock() != null) {
|
||||
progress(R.string.progress_modify_passphrase, 90);
|
||||
log.add(LogType.MSG_MF_PASSPHRASE, indent);
|
||||
indent += 1;
|
||||
|
||||
sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(),
|
||||
saveParcel.getChangeUnlockParcel().mNewPassphrase, log, indent);
|
||||
saveParcel.getNewUnlock().getNewPassphrase(), log, indent);
|
||||
if (sKR == null) {
|
||||
// The error has been logged above, just return a bad state
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
@@ -1074,21 +1102,21 @@ public class PgpKeyOperation {
|
||||
}
|
||||
|
||||
// 7. if requested, change PIN and/or Admin PIN on security token
|
||||
if (saveParcel.mSecurityTokenPin != null) {
|
||||
if (saveParcel.getSecurityTokenPin() != null) {
|
||||
progress(R.string.progress_modify_pin, 90);
|
||||
log.add(LogType.MSG_MF_PIN, indent);
|
||||
indent += 1;
|
||||
|
||||
nfcKeyToCardOps.setPin(saveParcel.mSecurityTokenPin);
|
||||
nfcKeyToCardOps.setPin(saveParcel.getSecurityTokenPin());
|
||||
|
||||
indent -= 1;
|
||||
}
|
||||
if (saveParcel.mSecurityTokenAdminPin != null) {
|
||||
if (saveParcel.getSecurityTokenAdminPin() != null) {
|
||||
progress(R.string.progress_modify_admin_pin, 90);
|
||||
log.add(LogType.MSG_MF_ADMIN_PIN, indent);
|
||||
indent += 1;
|
||||
|
||||
nfcKeyToCardOps.setAdminPin(saveParcel.mSecurityTokenAdminPin);
|
||||
nfcKeyToCardOps.setAdminPin(saveParcel.getSecurityTokenAdminPin());
|
||||
|
||||
indent -= 1;
|
||||
}
|
||||
@@ -1139,7 +1167,7 @@ public class PgpKeyOperation {
|
||||
progress(R.string.progress_modify, 0);
|
||||
|
||||
// Make sure the saveParcel includes only operations available without passphrase!
|
||||
if (!saveParcel.isRestrictedOnly()) {
|
||||
if (!isParcelRestrictedOnly(saveParcel)) {
|
||||
log.add(LogType.MSG_MF_ERROR_RESTRICTED, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
@@ -1153,36 +1181,36 @@ public class PgpKeyOperation {
|
||||
// The only operation we can do here:
|
||||
// 4a. Strip secret keys, or change their protection mode (stripped/divert-to-card)
|
||||
subProgressPush(50, 60);
|
||||
for (int i = 0; i < saveParcel.mChangeSubKeys.size(); i++) {
|
||||
|
||||
progress(R.string.progress_modify_subkeychange, (i - 1) * (100 / saveParcel.mChangeSubKeys.size()));
|
||||
SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i);
|
||||
List<SubkeyChange> changeSubKeys = saveParcel.getChangeSubKeys();
|
||||
for (int i = 0, j = changeSubKeys.size(); i < j; i++) {
|
||||
progress(R.string.progress_modify_subkeychange, (i - 1) * (100 / changeSubKeys.size()));
|
||||
SaveKeyringParcel.SubkeyChange change = changeSubKeys.get(i);
|
||||
log.add(LogType.MSG_MF_SUBKEY_CHANGE,
|
||||
indent, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
|
||||
indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
|
||||
|
||||
PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId);
|
||||
PGPSecretKey sKey = sKR.getSecretKey(change.getSubKeyId());
|
||||
if (sKey == null) {
|
||||
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
|
||||
if (change.mDummyStrip || change.mSecurityTokenSerialNo != null) {
|
||||
if (change.getDummyStrip() || change.getSecurityTokenSerialNo() != null) {
|
||||
// IT'S DANGEROUS~
|
||||
// no really, it is. this operation irrevocably removes the private key data from the key
|
||||
if (change.mDummyStrip) {
|
||||
if (change.getDummyStrip()) {
|
||||
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
|
||||
} else {
|
||||
// the serial number must be 16 bytes in length
|
||||
if (change.mSecurityTokenSerialNo.length != 16) {
|
||||
if (change.getSecurityTokenSerialNo().length != 16) {
|
||||
log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
|
||||
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
log.add(LogType.MSG_MF_KEYTOCARD_FINISH, indent + 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(change.mKeyId),
|
||||
Hex.toHexString(change.mSecurityTokenSerialNo, 8, 6));
|
||||
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.mSecurityTokenSerialNo);
|
||||
KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()),
|
||||
Hex.toHexString(change.getSecurityTokenSerialNo(), 8, 6));
|
||||
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.getSecurityTokenSerialNo());
|
||||
}
|
||||
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
|
||||
}
|
||||
@@ -1204,7 +1232,8 @@ public class PgpKeyOperation {
|
||||
OperationLog log = new OperationLog();
|
||||
int indent = 0;
|
||||
|
||||
if (changeUnlockParcel.mMasterKeyId == null || changeUnlockParcel.mMasterKeyId != wsKR.getMasterKeyId()) {
|
||||
Long masterKeyId = changeUnlockParcel.getMasterKeyId();
|
||||
if (masterKeyId == null || masterKeyId != wsKR.getMasterKeyId()) {
|
||||
log.add(LogType.MSG_MF_ERROR_KEYID, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
}
|
||||
@@ -1219,7 +1248,7 @@ public class PgpKeyOperation {
|
||||
PGPSecretKey masterSecretKey = sKR.getSecretKey();
|
||||
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
|
||||
// Make sure the fingerprint matches
|
||||
if (changeUnlockParcel.mFingerprint == null || !Arrays.equals(changeUnlockParcel.mFingerprint,
|
||||
if (changeUnlockParcel.getFingerprint()== null || !Arrays.equals(changeUnlockParcel.getFingerprint(),
|
||||
masterSecretKey.getPublicKey().getFingerprint())) {
|
||||
log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent);
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
@@ -1245,7 +1274,7 @@ public class PgpKeyOperation {
|
||||
|
||||
try {
|
||||
sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(),
|
||||
changeUnlockParcel.mNewPassphrase, log, indent);
|
||||
changeUnlockParcel.getNewPassphrase(), log, indent);
|
||||
if (sKR == null) {
|
||||
// The error has been logged above, just return a bad state
|
||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||
@@ -1697,4 +1726,31 @@ public class PgpKeyOperation {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Returns true iff this parcel does not contain any operations which require a passphrase. */
|
||||
private static boolean isParcelRestrictedOnly(SaveKeyringParcel saveKeyringParcel) {
|
||||
if (saveKeyringParcel.getNewUnlock() != null
|
||||
|| !saveKeyringParcel.getAddUserIds().isEmpty()
|
||||
|| !saveKeyringParcel.getAddUserAttribute().isEmpty()
|
||||
|| !saveKeyringParcel.getAddSubKeys().isEmpty()
|
||||
|| saveKeyringParcel.getChangePrimaryUserId() != null
|
||||
|| !saveKeyringParcel.getRevokeUserIds().isEmpty()
|
||||
|| !saveKeyringParcel.getRevokeSubKeys().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (SubkeyChange change : saveKeyringParcel.getChangeSubKeys()) {
|
||||
if (change.getRecertify() || change.getFlags() != null || change.getExpiry() != null
|
||||
|| change.getMoveKeyToSecurityToken()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isParcelEmpty(SaveKeyringParcel saveKeyringParcel) {
|
||||
return isParcelRestrictedOnly(saveKeyringParcel) && saveKeyringParcel.getChangeSubKeys().isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
|
||||
* Copyright (C) 2017 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
|
||||
@@ -18,226 +18,91 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainHashAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
@AutoValue
|
||||
public abstract class PgpSignEncryptData implements Parcelable {
|
||||
@Nullable
|
||||
public abstract String getCharset();
|
||||
abstract long getAdditionalEncryptId();
|
||||
@Nullable
|
||||
public abstract Long getSignatureSubKeyId();
|
||||
public abstract long getSignatureMasterKeyId();
|
||||
@Nullable
|
||||
public abstract Passphrase getSymmetricPassphrase();
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract long[] getEncryptionMasterKeyIds();
|
||||
@Nullable
|
||||
public abstract List<Long> getAllowedSigningKeyIds();
|
||||
@Nullable
|
||||
public abstract String getVersionHeader();
|
||||
|
||||
public class PgpSignEncryptData implements Parcelable {
|
||||
private String mVersionHeader = null;
|
||||
private boolean mEnableAsciiArmorOutput = false;
|
||||
private int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED;
|
||||
private long[] mEncryptionMasterKeyIds = null;
|
||||
private Passphrase mSymmetricPassphrase = null;
|
||||
private int mSymmetricEncryptionAlgorithm = PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT;
|
||||
private long mSignatureMasterKeyId = Constants.key.none;
|
||||
private Long mSignatureSubKeyId = null;
|
||||
private int mSignatureHashAlgorithm = PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT;
|
||||
private long mAdditionalEncryptId = Constants.key.none;
|
||||
private String mCharset;
|
||||
private boolean mCleartextSignature;
|
||||
private boolean mDetachedSignature = false;
|
||||
private boolean mHiddenRecipients = false;
|
||||
private boolean mAddBackupHeader = false;
|
||||
public abstract int getCompressionAlgorithm();
|
||||
public abstract int getSignatureHashAlgorithm();
|
||||
public abstract int getSymmetricEncryptionAlgorithm();
|
||||
|
||||
public PgpSignEncryptData(){
|
||||
public abstract boolean isEnableAsciiArmorOutput();
|
||||
public abstract boolean isCleartextSignature();
|
||||
public abstract boolean isDetachedSignature();
|
||||
public abstract boolean isAddBackupHeader();
|
||||
public abstract boolean isHiddenRecipients();
|
||||
|
||||
public static Builder builder() {
|
||||
return new AutoValue_PgpSignEncryptData.Builder()
|
||||
.setSignatureMasterKeyId(Constants.key.none)
|
||||
.setAdditionalEncryptId(Constants.key.none)
|
||||
.setEnableAsciiArmorOutput(false)
|
||||
.setCleartextSignature(false)
|
||||
.setDetachedSignature(false)
|
||||
.setAddBackupHeader(false)
|
||||
.setHiddenRecipients(false)
|
||||
.setCompressionAlgorithm(OpenKeychainCompressionAlgorithmTags.USE_DEFAULT)
|
||||
.setSignatureHashAlgorithm(OpenKeychainHashAlgorithmTags.USE_DEFAULT)
|
||||
.setSymmetricEncryptionAlgorithm(OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
|
||||
}
|
||||
|
||||
private PgpSignEncryptData(Parcel source) {
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
public abstract PgpSignEncryptData build();
|
||||
|
||||
mVersionHeader = source.readString();
|
||||
mEnableAsciiArmorOutput = source.readInt() == 1;
|
||||
mCompressionAlgorithm = source.readInt();
|
||||
mEncryptionMasterKeyIds = source.createLongArray();
|
||||
mSymmetricPassphrase = source.readParcelable(loader);
|
||||
mSymmetricEncryptionAlgorithm = source.readInt();
|
||||
mSignatureMasterKeyId = source.readLong();
|
||||
mSignatureSubKeyId = source.readInt() == 1 ? source.readLong() : null;
|
||||
mSignatureHashAlgorithm = source.readInt();
|
||||
mAdditionalEncryptId = source.readLong();
|
||||
mCharset = source.readString();
|
||||
mCleartextSignature = source.readInt() == 1;
|
||||
mDetachedSignature = source.readInt() == 1;
|
||||
mHiddenRecipients = source.readInt() == 1;
|
||||
mAddBackupHeader = source.readInt() == 1;
|
||||
}
|
||||
public abstract Builder setCharset(String charset);
|
||||
public abstract Builder setAdditionalEncryptId(long additionalEncryptId);
|
||||
public abstract Builder setSignatureSubKeyId(Long signatureSubKeyId);
|
||||
public abstract Builder setSignatureMasterKeyId(long signatureMasterKeyId);
|
||||
public abstract Builder setSymmetricPassphrase(Passphrase symmetricPassphrase);
|
||||
public abstract Builder setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds);
|
||||
public abstract Builder setVersionHeader(String versionHeader);
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
public abstract Builder setCompressionAlgorithm(int compressionAlgorithm);
|
||||
public abstract Builder setSignatureHashAlgorithm(int signatureHashAlgorithm);
|
||||
public abstract Builder setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm);
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mVersionHeader);
|
||||
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
|
||||
dest.writeInt(mCompressionAlgorithm);
|
||||
dest.writeLongArray(mEncryptionMasterKeyIds);
|
||||
dest.writeParcelable(mSymmetricPassphrase, 0);
|
||||
dest.writeInt(mSymmetricEncryptionAlgorithm);
|
||||
dest.writeLong(mSignatureMasterKeyId);
|
||||
if (mSignatureSubKeyId != null) {
|
||||
dest.writeInt(1);
|
||||
dest.writeLong(mSignatureSubKeyId);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
public abstract Builder setAddBackupHeader(boolean isAddBackupHeader);
|
||||
public abstract Builder setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput);
|
||||
public abstract Builder setCleartextSignature(boolean isCleartextSignature);
|
||||
public abstract Builder setDetachedSignature(boolean isDetachedSignature);
|
||||
public abstract Builder setHiddenRecipients(boolean isHiddenRecipients);
|
||||
|
||||
abstract Builder setAllowedSigningKeyIds(List<Long> allowedSigningKeyIds);
|
||||
public Builder setAllowedSigningKeyIds(Collection<Long> allowedSigningKeyIds) {
|
||||
setAllowedSigningKeyIds(Collections.unmodifiableList(new ArrayList<>(allowedSigningKeyIds)));
|
||||
return this;
|
||||
}
|
||||
dest.writeInt(mSignatureHashAlgorithm);
|
||||
dest.writeLong(mAdditionalEncryptId);
|
||||
dest.writeString(mCharset);
|
||||
dest.writeInt(mCleartextSignature ? 1 : 0);
|
||||
dest.writeInt(mDetachedSignature ? 1 : 0);
|
||||
dest.writeInt(mHiddenRecipients ? 1 : 0);
|
||||
dest.writeInt(mAddBackupHeader ? 1 : 0);
|
||||
}
|
||||
|
||||
public String getCharset() {
|
||||
return mCharset;
|
||||
}
|
||||
|
||||
public void setCharset(String mCharset) {
|
||||
this.mCharset = mCharset;
|
||||
}
|
||||
|
||||
public long getAdditionalEncryptId() {
|
||||
return mAdditionalEncryptId;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setAdditionalEncryptId(long additionalEncryptId) {
|
||||
mAdditionalEncryptId = additionalEncryptId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSignatureHashAlgorithm() {
|
||||
return mSignatureHashAlgorithm;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setSignatureHashAlgorithm(int signatureHashAlgorithm) {
|
||||
mSignatureHashAlgorithm = signatureHashAlgorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getSignatureSubKeyId() {
|
||||
return mSignatureSubKeyId;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setSignatureSubKeyId(long signatureSubKeyId) {
|
||||
mSignatureSubKeyId = signatureSubKeyId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getSignatureMasterKeyId() {
|
||||
return mSignatureMasterKeyId;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setSignatureMasterKeyId(long signatureMasterKeyId) {
|
||||
mSignatureMasterKeyId = signatureMasterKeyId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSymmetricEncryptionAlgorithm() {
|
||||
return mSymmetricEncryptionAlgorithm;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
|
||||
mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Passphrase getSymmetricPassphrase() {
|
||||
return mSymmetricPassphrase;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setSymmetricPassphrase(Passphrase symmetricPassphrase) {
|
||||
mSymmetricPassphrase = symmetricPassphrase;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long[] getEncryptionMasterKeyIds() {
|
||||
return mEncryptionMasterKeyIds;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) {
|
||||
mEncryptionMasterKeyIds = encryptionMasterKeyIds;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getCompressionAlgorithm() {
|
||||
return mCompressionAlgorithm;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setCompressionAlgorithm(int compressionAlgorithm) {
|
||||
mCompressionAlgorithm = compressionAlgorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isEnableAsciiArmorOutput() {
|
||||
return mEnableAsciiArmorOutput;
|
||||
}
|
||||
|
||||
public String getVersionHeader() {
|
||||
return mVersionHeader;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setVersionHeader(String versionHeader) {
|
||||
mVersionHeader = versionHeader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
|
||||
mEnableAsciiArmorOutput = enableAsciiArmorOutput;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setCleartextSignature(boolean cleartextSignature) {
|
||||
this.mCleartextSignature = cleartextSignature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isCleartextSignature() {
|
||||
return mCleartextSignature;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setDetachedSignature(boolean detachedSignature) {
|
||||
this.mDetachedSignature = detachedSignature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isDetachedSignature() {
|
||||
return mDetachedSignature;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setHiddenRecipients(boolean hiddenRecipients) {
|
||||
this.mHiddenRecipients = hiddenRecipients;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData setAddBackupHeader(boolean addBackupHeader) {
|
||||
this.mAddBackupHeader = addBackupHeader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isAddBackupHeader() {
|
||||
return mAddBackupHeader;
|
||||
}
|
||||
|
||||
public boolean isHiddenRecipients() {
|
||||
return mHiddenRecipients;
|
||||
}
|
||||
|
||||
public static final Creator<PgpSignEncryptData> CREATOR = new Creator<PgpSignEncryptData>() {
|
||||
public PgpSignEncryptData createFromParcel(final Parcel source) {
|
||||
return new PgpSignEncryptData(source);
|
||||
}
|
||||
|
||||
public PgpSignEncryptData[] newArray(final int size) {
|
||||
return new PgpSignEncryptData[size];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -18,104 +18,33 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
|
||||
public class PgpSignEncryptInputParcel implements Parcelable {
|
||||
@AutoValue
|
||||
public abstract class PgpSignEncryptInputParcel implements Parcelable {
|
||||
public abstract PgpSignEncryptData getData();
|
||||
@Nullable
|
||||
public abstract Uri getOutputUri();
|
||||
@Nullable
|
||||
public abstract Uri getInputUri();
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract byte[] getInputBytes();
|
||||
|
||||
private PgpSignEncryptData data;
|
||||
|
||||
private Uri mInputUri;
|
||||
private Uri mOutputUri;
|
||||
private byte[] mInputBytes;
|
||||
|
||||
private HashSet<Long> mAllowedKeyIds;
|
||||
|
||||
public PgpSignEncryptInputParcel(PgpSignEncryptData data) {
|
||||
this.data = data;
|
||||
public static PgpSignEncryptInputParcel createForBytes(
|
||||
PgpSignEncryptData signEncryptData, Uri outputUri, byte[] inputBytes) {
|
||||
return new AutoValue_PgpSignEncryptInputParcel(signEncryptData, outputUri, null, inputBytes);
|
||||
}
|
||||
|
||||
PgpSignEncryptInputParcel(Parcel source) {
|
||||
mInputUri = source.readParcelable(getClass().getClassLoader());
|
||||
mOutputUri = source.readParcelable(getClass().getClassLoader());
|
||||
mInputBytes = source.createByteArray();
|
||||
|
||||
data = source.readParcelable(getClass().getClassLoader());
|
||||
|
||||
mAllowedKeyIds = (HashSet<Long>) source.readSerializable();
|
||||
public static PgpSignEncryptInputParcel createForInputUri(
|
||||
PgpSignEncryptData signEncryptData, Uri outputUri, Uri inputUri) {
|
||||
return new AutoValue_PgpSignEncryptInputParcel(signEncryptData, outputUri, inputUri, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(mInputUri, 0);
|
||||
dest.writeParcelable(mOutputUri, 0);
|
||||
dest.writeByteArray(mInputBytes);
|
||||
|
||||
data.writeToParcel(dest, 0);
|
||||
|
||||
dest.writeSerializable(mAllowedKeyIds);
|
||||
}
|
||||
|
||||
public void setInputBytes(byte[] inputBytes) {
|
||||
this.mInputBytes = inputBytes;
|
||||
}
|
||||
|
||||
byte[] getInputBytes() {
|
||||
return mInputBytes;
|
||||
}
|
||||
|
||||
public PgpSignEncryptInputParcel setInputUri(Uri uri) {
|
||||
mInputUri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
Uri getInputUri() {
|
||||
return mInputUri;
|
||||
}
|
||||
|
||||
public PgpSignEncryptInputParcel setOutputUri(Uri uri) {
|
||||
mOutputUri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
Uri getOutputUri() {
|
||||
return mOutputUri;
|
||||
}
|
||||
|
||||
public void setData(PgpSignEncryptData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
HashSet<Long> getAllowedKeyIds() {
|
||||
return mAllowedKeyIds;
|
||||
}
|
||||
|
||||
public void setAllowedKeyIds(HashSet<Long> allowedKeyIds) {
|
||||
mAllowedKeyIds = allowedKeyIds;
|
||||
}
|
||||
|
||||
public static final Creator<PgpSignEncryptInputParcel> CREATOR = new Creator<PgpSignEncryptInputParcel>() {
|
||||
public PgpSignEncryptInputParcel createFromParcel(final Parcel source) {
|
||||
return new PgpSignEncryptInputParcel(source);
|
||||
}
|
||||
|
||||
public PgpSignEncryptInputParcel[] newArray(final int size) {
|
||||
return new PgpSignEncryptInputParcel[size];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,24 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
@@ -43,7 +61,11 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainHashAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
@@ -56,23 +78,6 @@ import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* This class supports a single, low-level, sign/encrypt operation.
|
||||
* <p/>
|
||||
@@ -148,7 +153,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
}
|
||||
}
|
||||
|
||||
PgpSignEncryptResult result = executeInternal(input, cryptoInput, inputData, outStream);
|
||||
PgpSignEncryptResult result = executeInternal(input.getData(), cryptoInput, inputData, outStream);
|
||||
if (outStream instanceof ByteArrayOutputStream) {
|
||||
byte[] outputData = ((ByteArrayOutputStream) outStream).toByteArray();
|
||||
result.setOutputBytes(outputData);
|
||||
@@ -158,41 +163,33 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public PgpSignEncryptResult execute(PgpSignEncryptInputParcel input, CryptoInputParcel cryptoInput,
|
||||
InputData inputData, OutputStream outputStream) {
|
||||
return executeInternal(input, cryptoInput, inputData, outputStream);
|
||||
public PgpSignEncryptResult execute(PgpSignEncryptData data, CryptoInputParcel cryptoInput,
|
||||
InputData inputData, OutputStream outputStream) {
|
||||
return executeInternal(data, cryptoInput, inputData, outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs and/or encrypts data based on parameters of class
|
||||
*/
|
||||
private PgpSignEncryptResult executeInternal(PgpSignEncryptInputParcel input, CryptoInputParcel cryptoInput,
|
||||
InputData inputData, OutputStream outputStream) {
|
||||
|
||||
private PgpSignEncryptResult executeInternal(PgpSignEncryptData data, CryptoInputParcel cryptoInput,
|
||||
InputData inputData, OutputStream outputStream) {
|
||||
int indent = 0;
|
||||
OperationLog log = new OperationLog();
|
||||
|
||||
log.add(LogType.MSG_PSE, indent);
|
||||
indent += 1;
|
||||
|
||||
PgpSignEncryptData data = input.getData();
|
||||
boolean enableSignature = data.getSignatureMasterKeyId() != Constants.key.none;
|
||||
boolean enableEncryption = ((data.getEncryptionMasterKeyIds() != null && data.getEncryptionMasterKeyIds().length > 0)
|
||||
|| data.getSymmetricPassphrase() != null);
|
||||
boolean enableCompression = (data.getCompressionAlgorithm() != CompressionAlgorithmTags.UNCOMPRESSED);
|
||||
|
||||
Log.d(Constants.TAG, "enableSignature:" + enableSignature
|
||||
+ "\nenableEncryption:" + enableEncryption
|
||||
+ "\nenableCompression:" + enableCompression
|
||||
+ "\nenableAsciiArmorOutput:" + data.isEnableAsciiArmorOutput()
|
||||
+ "\nisHiddenRecipients:" + data.isHiddenRecipients());
|
||||
|
||||
// add additional key id to encryption ids (mostly to do self-encryption)
|
||||
if (enableEncryption && data.getAdditionalEncryptId() != Constants.key.none) {
|
||||
data.setEncryptionMasterKeyIds(Arrays.copyOf(data.getEncryptionMasterKeyIds(), data.getEncryptionMasterKeyIds().length + 1));
|
||||
data.getEncryptionMasterKeyIds()[data.getEncryptionMasterKeyIds().length - 1] = data.getAdditionalEncryptId();
|
||||
int compressionAlgorithm = data.getCompressionAlgorithm();
|
||||
if (compressionAlgorithm == OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
|
||||
compressionAlgorithm = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
|
||||
}
|
||||
|
||||
Log.d(Constants.TAG, data.toString());
|
||||
|
||||
ArmoredOutputStream armorOut = null;
|
||||
OutputStream out;
|
||||
if (data.isEnableAsciiArmorOutput()) {
|
||||
@@ -221,20 +218,26 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
|
||||
try {
|
||||
long signingMasterKeyId = data.getSignatureMasterKeyId();
|
||||
long signingSubKeyId = data.getSignatureSubKeyId();
|
||||
|
||||
CanonicalizedSecretKeyRing signingKeyRing =
|
||||
mKeyRepository.getCanonicalizedSecretKeyRing(signingMasterKeyId);
|
||||
signingKey = signingKeyRing.getSecretKey(data.getSignatureSubKeyId());
|
||||
|
||||
if (input.getAllowedKeyIds() != null) {
|
||||
if (!input.getAllowedKeyIds().contains(signingMasterKeyId)) {
|
||||
// this key is in our db, but NOT allowed!
|
||||
log.add(LogType.MSG_PSE_ERROR_KEY_NOT_ALLOWED, indent + 1);
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_KEY_DISALLOWED, log);
|
||||
Long signingSubKeyId = data.getSignatureSubKeyId();
|
||||
if (signingSubKeyId == null) {
|
||||
try {
|
||||
signingSubKeyId = mKeyRepository.getCachedPublicKeyRing(signingMasterKeyId).getSecretSignId();
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
log.add(LogType.MSG_PSE_ERROR_KEY_SIGN, indent);
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
}
|
||||
|
||||
CanonicalizedSecretKeyRing signingKeyRing =
|
||||
mKeyRepository.getCanonicalizedSecretKeyRing(signingMasterKeyId);
|
||||
signingKey = signingKeyRing.getSecretKey(signingSubKeyId);
|
||||
|
||||
Collection<Long> allowedSigningKeyIds = data.getAllowedSigningKeyIds();
|
||||
if (allowedSigningKeyIds != null && !allowedSigningKeyIds.contains(signingMasterKeyId)) {
|
||||
// this key is in our db, but NOT allowed!
|
||||
log.add(LogType.MSG_PSE_ERROR_KEY_NOT_ALLOWED, indent + 1);
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_KEY_DISALLOWED, log);
|
||||
}
|
||||
|
||||
// Make sure key is not expired or revoked
|
||||
if (signingKeyRing.isExpired() || signingKeyRing.isRevoked()
|
||||
@@ -300,12 +303,6 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
log.add(LogType.MSG_PSE_ERROR_UNLOCK, indent);
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
// Use requested hash algo
|
||||
int requestedAlgorithm = data.getSignatureHashAlgorithm();
|
||||
if (requestedAlgorithm == PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) {
|
||||
data.setSignatureHashAlgorithm(PgpSecurityConstants.DEFAULT_HASH_ALGORITHM);
|
||||
}
|
||||
}
|
||||
updateProgress(R.string.progress_preparing_streams, 2, 100);
|
||||
|
||||
@@ -314,12 +311,12 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
if (enableEncryption) {
|
||||
|
||||
// Use requested encryption algo
|
||||
int algo = data.getSymmetricEncryptionAlgorithm();
|
||||
if (algo == PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) {
|
||||
algo = PgpSecurityConstants.DEFAULT_SYMMETRIC_ALGORITHM;
|
||||
int symmetricEncryptionAlgorithm = data.getSymmetricEncryptionAlgorithm();
|
||||
if (symmetricEncryptionAlgorithm == OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) {
|
||||
symmetricEncryptionAlgorithm = PgpSecurityConstants.DEFAULT_SYMMETRIC_ALGORITHM;
|
||||
}
|
||||
JcePGPDataEncryptorBuilder encryptorBuilder =
|
||||
new JcePGPDataEncryptorBuilder(algo)
|
||||
new JcePGPDataEncryptorBuilder(symmetricEncryptionAlgorithm)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
|
||||
.setWithIntegrityPacket(true);
|
||||
|
||||
@@ -336,36 +333,28 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
log.add(LogType.MSG_PSE_ASYMMETRIC, indent);
|
||||
|
||||
// Asymmetric encryption
|
||||
for (long id : data.getEncryptionMasterKeyIds()) {
|
||||
try {
|
||||
CanonicalizedPublicKeyRing keyRing = mKeyRepository.getCanonicalizedPublicKeyRing(
|
||||
KeyRings.buildUnifiedKeyRingUri(id));
|
||||
Set<Long> encryptSubKeyIds = keyRing.getEncryptIds();
|
||||
for (Long subKeyId : encryptSubKeyIds) {
|
||||
CanonicalizedPublicKey key = keyRing.getPublicKey(subKeyId);
|
||||
cPk.addMethod(key.getPubKeyEncryptionGenerator(data.isHiddenRecipients()));
|
||||
log.add(LogType.MSG_PSE_KEY_OK, indent + 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(subKeyId));
|
||||
}
|
||||
if (encryptSubKeyIds.isEmpty()) {
|
||||
log.add(LogType.MSG_PSE_KEY_WARN, indent + 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(id));
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
// Make sure key is not expired or revoked
|
||||
if (keyRing.isExpired() || keyRing.isRevoked()) {
|
||||
log.add(LogType.MSG_PSE_ERROR_REVOKED_OR_EXPIRED, indent);
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
} catch (KeyWritableRepository.NotFoundException e) {
|
||||
log.add(LogType.MSG_PSE_KEY_UNKNOWN, indent + 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(id));
|
||||
for (long encryptMasterKeyId : data.getEncryptionMasterKeyIds()) {
|
||||
boolean success = processEncryptionMasterKeyId(indent, log, data, cPk, encryptMasterKeyId);
|
||||
if (!success) {
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
}
|
||||
|
||||
long additionalEncryptId = data.getAdditionalEncryptId();
|
||||
if (additionalEncryptId != Constants.key.none) {
|
||||
boolean success = processEncryptionMasterKeyId(indent, log, data, cPk, additionalEncryptId);
|
||||
if (!success) {
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int signatureHashAlgorithm = data.getSignatureHashAlgorithm();
|
||||
if (signatureHashAlgorithm == OpenKeychainHashAlgorithmTags.USE_DEFAULT) {
|
||||
signatureHashAlgorithm = PgpSecurityConstants.DEFAULT_HASH_ALGORITHM;
|
||||
}
|
||||
|
||||
/* Initialize signature generator object for later usage */
|
||||
PGPSignatureGenerator signatureGenerator = null;
|
||||
if (enableSignature) {
|
||||
@@ -374,7 +363,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
try {
|
||||
boolean cleartext = data.isCleartextSignature() && data.isEnableAsciiArmorOutput() && !enableEncryption;
|
||||
signatureGenerator = signingKey.getDataSignatureGenerator(
|
||||
data.getSignatureHashAlgorithm(), cleartext,
|
||||
signatureHashAlgorithm, cleartext,
|
||||
cryptoInput.getCryptoData(), cryptoInput.getSignatureTime());
|
||||
} catch (PgpGeneralException e) {
|
||||
log.add(LogType.MSG_PSE_ERROR_NFC, indent);
|
||||
@@ -409,15 +398,10 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
|
||||
encryptionOut = cPk.open(out, new byte[1 << 16]);
|
||||
|
||||
if (enableCompression) {
|
||||
if (compressionAlgorithm != CompressionAlgorithmTags.UNCOMPRESSED) {
|
||||
log.add(LogType.MSG_PSE_COMPRESSING, indent);
|
||||
|
||||
// Use preferred compression algo
|
||||
int algo = data.getCompressionAlgorithm();
|
||||
if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
|
||||
algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
|
||||
}
|
||||
compressGen = new PGPCompressedDataGenerator(algo);
|
||||
compressGen = new PGPCompressedDataGenerator(compressionAlgorithm);
|
||||
bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut));
|
||||
} else {
|
||||
bcpgOut = new BCPGOutputStream(encryptionOut);
|
||||
@@ -466,7 +450,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
log.add(LogType.MSG_PSE_SIGNING_CLEARTEXT, indent);
|
||||
|
||||
// write -----BEGIN PGP SIGNED MESSAGE-----
|
||||
armorOut.beginClearText(data.getSignatureHashAlgorithm());
|
||||
armorOut.beginClearText(signatureHashAlgorithm);
|
||||
|
||||
InputStream in = new BufferedInputStream(inputData.getInputStream());
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
@@ -539,14 +523,10 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
|
||||
InputStream in = new BufferedInputStream(inputData.getInputStream());
|
||||
|
||||
if (enableCompression) {
|
||||
// Use preferred compression algo
|
||||
int algo = data.getCompressionAlgorithm();
|
||||
if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
|
||||
algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
|
||||
}
|
||||
if (compressionAlgorithm != CompressionAlgorithmTags.UNCOMPRESSED) {
|
||||
log.add(LogType.MSG_PSE_COMPRESSING, indent);
|
||||
|
||||
compressGen = new PGPCompressedDataGenerator(algo);
|
||||
compressGen = new PGPCompressedDataGenerator(compressionAlgorithm);
|
||||
bcpgOut = new BCPGOutputStream(compressGen.open(out));
|
||||
} else {
|
||||
bcpgOut = new BCPGOutputStream(out);
|
||||
@@ -597,16 +577,15 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
}
|
||||
|
||||
opTime = System.currentTimeMillis() - startTime;
|
||||
Log.d(Constants.TAG, "sign/encrypt time taken: " + String.format("%.2f",
|
||||
opTime / 1000.0) + "s");
|
||||
Log.d(Constants.TAG, "sign/encrypt time taken: " + String.format("%.2f", opTime / 1000.0) + "s");
|
||||
|
||||
// closing outputs
|
||||
// NOTE: closing needs to be done in the correct order!
|
||||
if (encryptionOut != null) {
|
||||
if (compressGen != null) {
|
||||
compressGen.close();
|
||||
}
|
||||
if (compressGen != null) {
|
||||
compressGen.close();
|
||||
}
|
||||
|
||||
if (encryptionOut != null) {
|
||||
encryptionOut.close();
|
||||
}
|
||||
// Note: Closing ArmoredOutputStream does not close the underlying stream
|
||||
@@ -653,7 +632,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
}
|
||||
result.setDetachedSignature(detachedByteOut.toByteArray());
|
||||
try {
|
||||
String digestName = PGPUtil.getDigestName(data.getSignatureHashAlgorithm());
|
||||
String digestName = PGPUtil.getDigestName(signatureHashAlgorithm);
|
||||
// construct micalg parameter according to https://tools.ietf.org/html/rfc3156#section-5
|
||||
result.setMicAlgDigestName("pgp-" + digestName.toLowerCase());
|
||||
} catch (PGPException e) {
|
||||
@@ -663,6 +642,36 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean processEncryptionMasterKeyId(int indent, OperationLog log, PgpSignEncryptData data,
|
||||
PGPEncryptedDataGenerator cPk, long encryptMasterKeyId) {
|
||||
try {
|
||||
CanonicalizedPublicKeyRing keyRing = mKeyRepository.getCanonicalizedPublicKeyRing(
|
||||
KeyRings.buildUnifiedKeyRingUri(encryptMasterKeyId));
|
||||
Set<Long> encryptSubKeyIds = keyRing.getEncryptIds();
|
||||
for (Long subKeyId : encryptSubKeyIds) {
|
||||
CanonicalizedPublicKey key = keyRing.getPublicKey(subKeyId);
|
||||
cPk.addMethod(key.getPubKeyEncryptionGenerator(data.isHiddenRecipients()));
|
||||
log.add(LogType.MSG_PSE_KEY_OK, indent + 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(subKeyId));
|
||||
}
|
||||
if (encryptSubKeyIds.isEmpty()) {
|
||||
log.add(LogType.MSG_PSE_KEY_WARN, indent + 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(encryptMasterKeyId));
|
||||
return false;
|
||||
}
|
||||
// Make sure key is not expired or revoked
|
||||
if (keyRing.isExpired() || keyRing.isRevoked()) {
|
||||
log.add(LogType.MSG_PSE_ERROR_REVOKED_OR_EXPIRED, indent);
|
||||
return false;
|
||||
}
|
||||
} catch (KeyWritableRepository.NotFoundException e) {
|
||||
log.add(LogType.MSG_PSE_KEY_UNKNOWN, indent + 1,
|
||||
KeyFormattingUtils.convertKeyIdToHex(encryptMasterKeyId));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove whitespaces on line endings
|
||||
*/
|
||||
|
||||
@@ -19,14 +19,17 @@
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
|
||||
/**
|
||||
* This parcel stores the input of one or more PgpSignEncrypt operations.
|
||||
* All operations will use the same general parameters, differing only in
|
||||
@@ -39,83 +42,65 @@ import java.util.List;
|
||||
* - Once the output uris are empty, there must be exactly one input (uri xor bytes)
|
||||
* left, which will be returned in a byte array as part of the result parcel.
|
||||
*/
|
||||
public class SignEncryptParcel implements Parcelable {
|
||||
@AutoValue
|
||||
public abstract class SignEncryptParcel implements Parcelable {
|
||||
public abstract PgpSignEncryptData getSignEncryptData();
|
||||
public abstract List<Uri> getInputUris();
|
||||
public abstract List<Uri> getOutputUris();
|
||||
@SuppressWarnings("mutable")
|
||||
@Nullable
|
||||
public abstract byte[] getBytes();
|
||||
|
||||
private PgpSignEncryptData data;
|
||||
|
||||
public ArrayList<Uri> mInputUris = new ArrayList<>();
|
||||
public ArrayList<Uri> mOutputUris = new ArrayList<>();
|
||||
public byte[] mBytes;
|
||||
|
||||
public SignEncryptParcel(PgpSignEncryptData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public SignEncryptParcel(Parcel src) {
|
||||
mInputUris = src.createTypedArrayList(Uri.CREATOR);
|
||||
mOutputUris = src.createTypedArrayList(Uri.CREATOR);
|
||||
mBytes = src.createByteArray();
|
||||
|
||||
data = src.readParcelable(getClass().getClassLoader());
|
||||
}
|
||||
|
||||
public boolean isIncomplete() {
|
||||
return mInputUris.size() > mOutputUris.size();
|
||||
List<Uri> inputUris = getInputUris();
|
||||
List<Uri> outputUris = getOutputUris();
|
||||
if (inputUris == null || outputUris == null) {
|
||||
throw new IllegalStateException("Invalid operation for bytes-backed SignEncryptParcel!");
|
||||
}
|
||||
return inputUris.size() > outputUris.size();
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return mBytes;
|
||||
|
||||
public static SignEncryptParcel createSignEncryptParcel(PgpSignEncryptData signEncryptData, byte[] bytes) {
|
||||
// noinspection unchecked, it's ok for the empty list
|
||||
return new AutoValue_SignEncryptParcel(signEncryptData, Collections.EMPTY_LIST, Collections.EMPTY_LIST, bytes);
|
||||
}
|
||||
|
||||
public void setBytes(byte[] bytes) {
|
||||
mBytes = bytes;
|
||||
public static Builder builder(SignEncryptParcel signEncryptParcel) {
|
||||
return new Builder(signEncryptParcel.getSignEncryptData())
|
||||
.addInputUris(signEncryptParcel.getInputUris())
|
||||
.addOutputUris(signEncryptParcel.getOutputUris());
|
||||
}
|
||||
|
||||
public List<Uri> getInputUris() {
|
||||
return Collections.unmodifiableList(mInputUris);
|
||||
public static Builder builder(PgpSignEncryptData signEncryptData) {
|
||||
return new Builder(signEncryptData);
|
||||
}
|
||||
|
||||
public void addInputUris(Collection<Uri> inputUris) {
|
||||
mInputUris.addAll(inputUris);
|
||||
}
|
||||
|
||||
public List<Uri> getOutputUris() {
|
||||
return Collections.unmodifiableList(mOutputUris);
|
||||
}
|
||||
public static class Builder {
|
||||
private final PgpSignEncryptData signEncryptData;
|
||||
private ArrayList<Uri> inputUris = new ArrayList<>();
|
||||
private ArrayList<Uri> outputUris = new ArrayList<>();
|
||||
|
||||
public void addOutputUris(ArrayList<Uri> outputUris) {
|
||||
mOutputUris.addAll(outputUris);
|
||||
}
|
||||
|
||||
public void setData(PgpSignEncryptData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public PgpSignEncryptData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeTypedList(mInputUris);
|
||||
dest.writeTypedList(mOutputUris);
|
||||
dest.writeByteArray(mBytes);
|
||||
|
||||
dest.writeParcelable(data, 0);
|
||||
}
|
||||
|
||||
public static final Creator<SignEncryptParcel> CREATOR = new Creator<SignEncryptParcel>() {
|
||||
public SignEncryptParcel createFromParcel(final Parcel source) {
|
||||
return new SignEncryptParcel(source);
|
||||
private Builder(PgpSignEncryptData signEncryptData) {
|
||||
this.signEncryptData = signEncryptData;
|
||||
}
|
||||
|
||||
public SignEncryptParcel[] newArray(final int size) {
|
||||
return new SignEncryptParcel[size];
|
||||
public SignEncryptParcel build() {
|
||||
return new AutoValue_SignEncryptParcel(signEncryptData,
|
||||
Collections.unmodifiableList(inputUris),
|
||||
Collections.unmodifiableList(outputUris),
|
||||
null);
|
||||
}
|
||||
};
|
||||
|
||||
public Builder addOutputUris(Collection<Uri> outputUris) {
|
||||
this.outputUris.addAll(outputUris);
|
||||
return this;
|
||||
}
|
||||
public Builder addInputUris(Collection<Uri> inputUris) {
|
||||
this.inputUris.addAll(inputUris);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.bouncycastle.bcpg.BCPGInputStream;
|
||||
import org.bouncycastle.bcpg.BCPGOutputStream;
|
||||
import org.bouncycastle.bcpg.Packet;
|
||||
|
||||
@@ -22,6 +22,7 @@ package org.sufficientlysecure.keychain.remote;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@@ -56,9 +57,8 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem;
|
||||
@@ -109,12 +109,11 @@ public class OpenPgpService extends Service {
|
||||
boolean asciiArmor = cleartextSign || data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
|
||||
|
||||
// sign-only
|
||||
PgpSignEncryptData pgpData = new PgpSignEncryptData();
|
||||
PgpSignEncryptData.Builder pgpData = PgpSignEncryptData.builder();
|
||||
pgpData.setEnableAsciiArmorOutput(asciiArmor)
|
||||
.setCleartextSignature(cleartextSign)
|
||||
.setDetachedSignature(!cleartextSign)
|
||||
.setVersionHeader(null)
|
||||
.setSignatureHashAlgorithm(PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT);
|
||||
.setVersionHeader(null);
|
||||
|
||||
|
||||
Intent signKeyIdIntent = getSignKeyMasterId(data);
|
||||
@@ -132,17 +131,13 @@ public class OpenPgpService extends Service {
|
||||
|
||||
// get first usable subkey capable of signing
|
||||
try {
|
||||
long signSubKeyId = mKeyRepository.getCachedPublicKeyRing(
|
||||
pgpData.getSignatureMasterKeyId()).getSecretSignId();
|
||||
long signSubKeyId = mKeyRepository.getCachedPublicKeyRing(signKeyId).getSecretSignId();
|
||||
pgpData.setSignatureSubKeyId(signSubKeyId);
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
throw new Exception("signing subkey not found!", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel(pgpData);
|
||||
pseInput.setAllowedKeyIds(getAllowedKeyIds());
|
||||
pgpData.setAllowedSigningKeyIds(getAllowedKeyIds());
|
||||
|
||||
// Get Input- and OutputStream from ParcelFileDescriptor
|
||||
if (!cleartextSign) {
|
||||
@@ -155,17 +150,17 @@ public class OpenPgpService extends Service {
|
||||
|
||||
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
|
||||
if (inputParcel == null) {
|
||||
inputParcel = new CryptoInputParcel(new Date());
|
||||
inputParcel = CryptoInputParcel.createCryptoInputParcel(new Date());
|
||||
}
|
||||
// override passphrase in input parcel if given by API call
|
||||
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
|
||||
inputParcel.mPassphrase =
|
||||
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
|
||||
inputParcel = inputParcel.withPassphrase(
|
||||
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
|
||||
}
|
||||
|
||||
// execute PGP operation!
|
||||
PgpSignEncryptOperation pse = new PgpSignEncryptOperation(this, mKeyRepository, null);
|
||||
PgpSignEncryptResult pgpResult = pse.execute(pseInput, inputParcel, inputData, outputStream);
|
||||
PgpSignEncryptResult pgpResult = pse.execute(pgpData.build(), inputParcel, inputData, outputStream);
|
||||
|
||||
if (pgpResult.isPending()) {
|
||||
RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel();
|
||||
@@ -205,18 +200,14 @@ public class OpenPgpService extends Service {
|
||||
originalFilename = "";
|
||||
}
|
||||
|
||||
boolean enableCompression = data.getBooleanExtra(OpenPgpApi.EXTRA_ENABLE_COMPRESSION, true);
|
||||
int compressionId;
|
||||
if (enableCompression) {
|
||||
compressionId = PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT;
|
||||
} else {
|
||||
compressionId = PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED;
|
||||
}
|
||||
PgpSignEncryptData.Builder pgpData = PgpSignEncryptData.builder()
|
||||
.setEnableAsciiArmorOutput(asciiArmor)
|
||||
.setVersionHeader(null);
|
||||
|
||||
PgpSignEncryptData pgpData = new PgpSignEncryptData();
|
||||
pgpData.setEnableAsciiArmorOutput(asciiArmor)
|
||||
.setVersionHeader(null)
|
||||
.setCompressionAlgorithm(compressionId);
|
||||
boolean enableCompression = data.getBooleanExtra(OpenPgpApi.EXTRA_ENABLE_COMPRESSION, true);
|
||||
if (!enableCompression) {
|
||||
pgpData.setCompressionAlgorithm(OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
|
||||
}
|
||||
|
||||
if (sign) {
|
||||
Intent signKeyIdIntent = getSignKeyMasterId(data);
|
||||
@@ -260,17 +251,16 @@ public class OpenPgpService extends Service {
|
||||
return result;
|
||||
}
|
||||
pgpData.setEncryptionMasterKeyIds(keyIdResult.getKeyIds());
|
||||
|
||||
PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel(pgpData);
|
||||
pseInput.setAllowedKeyIds(getAllowedKeyIds());
|
||||
pgpData.setAllowedSigningKeyIds(getAllowedKeyIds());
|
||||
|
||||
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
|
||||
if (inputParcel == null) {
|
||||
inputParcel = new CryptoInputParcel(new Date());
|
||||
inputParcel = CryptoInputParcel.createCryptoInputParcel(new Date());
|
||||
}
|
||||
// override passphrase in input parcel if given by API call
|
||||
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
|
||||
inputParcel.mPassphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
|
||||
inputParcel = inputParcel.withPassphrase(
|
||||
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
|
||||
}
|
||||
|
||||
// TODO this is not correct!
|
||||
@@ -279,7 +269,7 @@ public class OpenPgpService extends Service {
|
||||
|
||||
// execute PGP operation!
|
||||
PgpSignEncryptOperation op = new PgpSignEncryptOperation(this, mKeyRepository, null);
|
||||
PgpSignEncryptResult pgpResult = op.execute(pseInput, inputParcel, inputData, outputStream);
|
||||
PgpSignEncryptResult pgpResult = op.execute(pgpData.build(), inputParcel, inputData, outputStream);
|
||||
|
||||
if (pgpResult.isPending()) {
|
||||
RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel();
|
||||
@@ -353,17 +343,18 @@ public class OpenPgpService extends Service {
|
||||
|
||||
CryptoInputParcel cryptoInput = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
|
||||
if (cryptoInput == null) {
|
||||
cryptoInput = new CryptoInputParcel();
|
||||
cryptoInput = CryptoInputParcel.createCryptoInputParcel();
|
||||
}
|
||||
// override passphrase in input parcel if given by API call
|
||||
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
|
||||
cryptoInput.mPassphrase =
|
||||
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
|
||||
cryptoInput = cryptoInput.withPassphrase(
|
||||
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
|
||||
}
|
||||
if (data.hasExtra(OpenPgpApi.EXTRA_DECRYPTION_RESULT)) {
|
||||
OpenPgpDecryptionResult decryptionResult = data.getParcelableExtra(OpenPgpApi.EXTRA_DECRYPTION_RESULT);
|
||||
if (decryptionResult != null && decryptionResult.hasDecryptedSessionKey()) {
|
||||
cryptoInput.addCryptoData(decryptionResult.getSessionKey(), decryptionResult.getDecryptedSessionKey());
|
||||
cryptoInput = cryptoInput.withCryptoData(
|
||||
decryptionResult.getSessionKey(), decryptionResult.getDecryptedSessionKey());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,12 +368,13 @@ public class OpenPgpService extends Service {
|
||||
|
||||
// allow only private keys associated with accounts of this app
|
||||
// no support for symmetric encryption
|
||||
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel()
|
||||
PgpDecryptVerifyInputParcel input = PgpDecryptVerifyInputParcel.builder()
|
||||
.setAllowSymmetricDecryption(false)
|
||||
.setAllowedKeyIds(getAllowedKeyIds())
|
||||
.setAllowedKeyIds(new ArrayList<>(getAllowedKeyIds()))
|
||||
.setDecryptMetadataOnly(decryptMetadataOnly)
|
||||
.setDetachedSignature(detachedSignature)
|
||||
.setSenderAddress(senderAddress);
|
||||
.setSenderAddress(senderAddress)
|
||||
.build();
|
||||
|
||||
DecryptVerifyResult pgpResult = op.execute(input, cryptoInput, inputData, outputStream);
|
||||
|
||||
@@ -657,7 +649,8 @@ public class OpenPgpService extends Service {
|
||||
// after user interaction with RemoteBackupActivity,
|
||||
// the backup code is cached in CryptoInputParcelCacheService, now we can proceed
|
||||
|
||||
BackupKeyringParcel input = new BackupKeyringParcel(masterKeyIds, backupSecret, true, enableAsciiArmorOutput, null);
|
||||
BackupKeyringParcel input = BackupKeyringParcel
|
||||
.createBackupKeyringParcel(masterKeyIds, backupSecret, true, enableAsciiArmorOutput, null);
|
||||
BackupOperation op = new BackupOperation(this, mKeyRepository, null);
|
||||
ExportResult pgpResult = op.execute(input, inputParcel, outputStream);
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||
import org.bouncycastle.math.ec.ECCurve;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
|
||||
|
||||
|
||||
// 4.3.3.6 Algorithm Attributes
|
||||
public class ECKeyFormat extends KeyFormat {
|
||||
@@ -84,7 +86,7 @@ public class ECKeyFormat extends KeyFormat {
|
||||
}
|
||||
}
|
||||
|
||||
public void addToSaveKeyringParcel(SaveKeyringParcel keyring, int keyFlags) {
|
||||
public void addToSaveKeyringParcel(SaveKeyringParcel.Builder builder, int keyFlags) {
|
||||
final X9ECParameters params = NISTNamedCurves.getByOID(mECCurveOID);
|
||||
final ECCurve curve = params.getCurve();
|
||||
|
||||
@@ -105,7 +107,6 @@ public class ECKeyFormat extends KeyFormat {
|
||||
throw new IllegalArgumentException("Unsupported curve " + mECCurveOID);
|
||||
}
|
||||
|
||||
keyring.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(algo,
|
||||
curve.getFieldSize(), scurve, keyFlags, 0L));
|
||||
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(algo, curve.getFieldSize(), scurve, keyFlags, 0L));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,6 @@ public abstract class KeyFormat {
|
||||
throw new IllegalArgumentException("Unsupported Algorithm id " + t);
|
||||
}
|
||||
|
||||
public abstract void addToSaveKeyringParcel(SaveKeyringParcel keyring, int keyFlags);
|
||||
public abstract void addToSaveKeyringParcel(SaveKeyringParcel.Builder builder, int keyFlags);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
package org.sufficientlysecure.keychain.securitytoken;
|
||||
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
|
||||
|
||||
|
||||
// 4.3.3.6 Algorithm Attributes
|
||||
public class RSAKeyFormat extends KeyFormat {
|
||||
@@ -84,8 +86,8 @@ public class RSAKeyFormat extends KeyFormat {
|
||||
}
|
||||
}
|
||||
|
||||
public void addToSaveKeyringParcel(SaveKeyringParcel keyring, int keyFlags) {
|
||||
keyring.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
|
||||
public void addToSaveKeyringParcel(SaveKeyringParcel.Builder builder, int keyFlags) {
|
||||
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
|
||||
mModulusLength, null, keyFlags, 0L));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,61 +19,28 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
|
||||
public class BackupKeyringParcel implements Parcelable {
|
||||
public Uri mCanonicalizedPublicKeyringUri;
|
||||
@AutoValue
|
||||
public abstract class BackupKeyringParcel implements Parcelable {
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract long[] getMasterKeyIds();
|
||||
public abstract boolean getExportSecret();
|
||||
public abstract boolean getIsEncrypted();
|
||||
public abstract boolean getEnableAsciiArmorOutput();
|
||||
@Nullable
|
||||
public abstract Uri getOutputUri();
|
||||
|
||||
public final boolean mExportSecret;
|
||||
public final boolean mIsEncrypted;
|
||||
public final boolean mEnableAsciiArmorOutput;
|
||||
public final long mMasterKeyIds[];
|
||||
public final Uri mOutputUri;
|
||||
|
||||
public BackupKeyringParcel(long[] masterKeyIds, boolean exportSecret, boolean isEncrypted, boolean enableAsciiArmorOutput, Uri outputUri) {
|
||||
mMasterKeyIds = masterKeyIds;
|
||||
mExportSecret = exportSecret;
|
||||
mOutputUri = outputUri;
|
||||
mIsEncrypted = isEncrypted;
|
||||
mEnableAsciiArmorOutput = enableAsciiArmorOutput;
|
||||
public static BackupKeyringParcel createBackupKeyringParcel(long[] masterKeyIds, boolean exportSecret,
|
||||
boolean isEncrypted, boolean enableAsciiArmorOutput, Uri outputUri) {
|
||||
return new AutoValue_BackupKeyringParcel(
|
||||
masterKeyIds, exportSecret, isEncrypted, enableAsciiArmorOutput, outputUri);
|
||||
}
|
||||
|
||||
protected BackupKeyringParcel(Parcel in) {
|
||||
mCanonicalizedPublicKeyringUri = (Uri) in.readValue(Uri.class.getClassLoader());
|
||||
mExportSecret = in.readByte() != 0x00;
|
||||
mOutputUri = (Uri) in.readValue(Uri.class.getClassLoader());
|
||||
mMasterKeyIds = in.createLongArray();
|
||||
mIsEncrypted = in.readInt() != 0;
|
||||
mEnableAsciiArmorOutput = in.readInt() != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeValue(mCanonicalizedPublicKeyringUri);
|
||||
dest.writeByte((byte) (mExportSecret ? 0x01 : 0x00));
|
||||
dest.writeValue(mOutputUri);
|
||||
dest.writeLongArray(mMasterKeyIds);
|
||||
dest.writeInt(mIsEncrypted ? 1 : 0);
|
||||
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<BackupKeyringParcel> CREATOR = new Parcelable.Creator<BackupKeyringParcel>() {
|
||||
@Override
|
||||
public BackupKeyringParcel createFromParcel(Parcel in) {
|
||||
return new BackupKeyringParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackupKeyringParcel[] newArray(int size) {
|
||||
return new BackupKeyringParcel[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -19,36 +19,16 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
public class BenchmarkInputParcel implements Parcelable {
|
||||
|
||||
public BenchmarkInputParcel() {
|
||||
@AutoValue
|
||||
public abstract class BenchmarkInputParcel implements Parcelable {
|
||||
|
||||
public static BenchmarkInputParcel newInstance() {
|
||||
return new AutoValue_BenchmarkInputParcel();
|
||||
}
|
||||
|
||||
protected BenchmarkInputParcel(Parcel in) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
}
|
||||
|
||||
public static final Creator<BenchmarkInputParcel> CREATOR = new Creator<BenchmarkInputParcel>() {
|
||||
@Override
|
||||
public BenchmarkInputParcel createFromParcel(Parcel in) {
|
||||
return new BenchmarkInputParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BenchmarkInputParcel[] newArray(int size) {
|
||||
return new BenchmarkInputParcel[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -18,99 +18,80 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
|
||||
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
||||
|
||||
|
||||
/**
|
||||
* This class is a a transferable representation for a number of keyrings to
|
||||
* be certified.
|
||||
*/
|
||||
public class CertifyActionsParcel implements Parcelable {
|
||||
@AutoValue
|
||||
public abstract class CertifyActionsParcel implements Parcelable {
|
||||
public abstract long getMasterKeyId();
|
||||
public abstract ArrayList<CertifyAction> getCertifyActions();
|
||||
@Nullable
|
||||
public abstract ParcelableHkpKeyserver getParcelableKeyServer();
|
||||
|
||||
// the master key id to certify with
|
||||
final public long mMasterKeyId;
|
||||
public CertifyLevel mLevel;
|
||||
|
||||
public ArrayList<CertifyAction> mCertifyActions = new ArrayList<>();
|
||||
|
||||
public ParcelableHkpKeyserver keyServerUri;
|
||||
|
||||
public CertifyActionsParcel(long masterKeyId) {
|
||||
mMasterKeyId = masterKeyId;
|
||||
mLevel = CertifyLevel.DEFAULT;
|
||||
public static Builder builder(long masterKeyId) {
|
||||
return new AutoValue_CertifyActionsParcel.Builder()
|
||||
.setMasterKeyId(masterKeyId)
|
||||
.setCertifyActions(new ArrayList<CertifyAction>());
|
||||
}
|
||||
|
||||
public CertifyActionsParcel(Parcel source) {
|
||||
mMasterKeyId = source.readLong();
|
||||
// just like parcelables, this is meant for ad-hoc IPC only and is NOT portable!
|
||||
mLevel = CertifyLevel.values()[source.readInt()];
|
||||
keyServerUri = source.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
abstract Builder setMasterKeyId(long masterKeyId);
|
||||
public abstract Builder setCertifyActions(ArrayList<CertifyAction> certifyActions);
|
||||
public abstract Builder setParcelableKeyServer(ParcelableHkpKeyserver uri);
|
||||
|
||||
mCertifyActions = (ArrayList<CertifyAction>) source.readSerializable();
|
||||
}
|
||||
abstract ArrayList<CertifyAction> getCertifyActions();
|
||||
|
||||
public void add(CertifyAction action) {
|
||||
mCertifyActions.add(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel destination, int flags) {
|
||||
destination.writeLong(mMasterKeyId);
|
||||
destination.writeInt(mLevel.ordinal());
|
||||
destination.writeParcelable(keyServerUri, flags);
|
||||
|
||||
destination.writeSerializable(mCertifyActions);
|
||||
}
|
||||
|
||||
public static final Creator<CertifyActionsParcel> CREATOR = new Creator<CertifyActionsParcel>() {
|
||||
public CertifyActionsParcel createFromParcel(final Parcel source) {
|
||||
return new CertifyActionsParcel(source);
|
||||
public void addAction(CertifyAction action) {
|
||||
getCertifyActions().add(action);
|
||||
}
|
||||
public void addActions(Collection<CertifyAction> certifyActions) {
|
||||
getCertifyActions().addAll(certifyActions);
|
||||
}
|
||||
|
||||
public CertifyActionsParcel[] newArray(final int size) {
|
||||
return new CertifyActionsParcel[size];
|
||||
public abstract CertifyActionsParcel build();
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
public abstract static class CertifyAction implements Parcelable {
|
||||
public abstract long getMasterKeyId();
|
||||
@Nullable
|
||||
public abstract ArrayList<String> getUserIds();
|
||||
@Nullable
|
||||
public abstract ArrayList<WrappedUserAttribute> getUserAttributes();
|
||||
|
||||
public static CertifyAction createForUserIds(long masterKeyId, List<String> userIds) {
|
||||
return new AutoValue_CertifyActionsParcel_CertifyAction(masterKeyId, new ArrayList<>(userIds), null);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO make this parcelable
|
||||
public static class CertifyAction implements Serializable {
|
||||
final public long mMasterKeyId;
|
||||
public static CertifyAction createForUserAttributes(long masterKeyId, List<WrappedUserAttribute> attributes) {
|
||||
return new AutoValue_CertifyActionsParcel_CertifyAction(masterKeyId, null, new ArrayList<>(attributes));
|
||||
}
|
||||
|
||||
final public ArrayList<String> mUserIds;
|
||||
final public ArrayList<WrappedUserAttribute> mUserAttributes;
|
||||
@CheckResult
|
||||
public CertifyAction withAddedUserIds(ArrayList<String> addedUserIds) {
|
||||
if (getUserAttributes() != null) {
|
||||
throw new IllegalStateException("Can't add user ids to user attribute certification parcel!");
|
||||
}
|
||||
ArrayList<String> prevUserIds = getUserIds();
|
||||
if (prevUserIds == null) {
|
||||
throw new IllegalStateException("Can't add user ids to user attribute certification parcel!");
|
||||
}
|
||||
|
||||
public CertifyAction(long masterKeyId, List<String> userIds, List<WrappedUserAttribute> attributes) {
|
||||
mMasterKeyId = masterKeyId;
|
||||
mUserIds = userIds == null ? null : new ArrayList<>(userIds);
|
||||
mUserAttributes = attributes == null ? null : new ArrayList<>(attributes);
|
||||
ArrayList<String> userIds = new ArrayList<>(prevUserIds);
|
||||
userIds.addAll(addedUserIds);
|
||||
return new AutoValue_CertifyActionsParcel_CertifyAction(getMasterKeyId(), userIds, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String out = "mMasterKeyId: " + mMasterKeyId + "\n";
|
||||
out += "mLevel: " + mLevel + "\n";
|
||||
out += "mCertifyActions: " + mCertifyActions + "\n";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// All supported algorithms
|
||||
public enum CertifyLevel {
|
||||
DEFAULT, NONE, CASUAL, POSITIVE
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,70 +19,29 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
public class ChangeUnlockParcel implements Parcelable {
|
||||
@AutoValue
|
||||
public abstract class ChangeUnlockParcel implements Parcelable {
|
||||
@Nullable
|
||||
public abstract Long getMasterKeyId();
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract byte[] getFingerprint();
|
||||
public abstract Passphrase getNewPassphrase();
|
||||
|
||||
// the master key id of keyring.
|
||||
public Long mMasterKeyId;
|
||||
// the key fingerprint, for safety.
|
||||
public byte[] mFingerprint;
|
||||
// The new passphrase to use
|
||||
public final Passphrase mNewPassphrase;
|
||||
|
||||
public ChangeUnlockParcel(Passphrase newPassphrase) {
|
||||
mNewPassphrase = newPassphrase;
|
||||
public static ChangeUnlockParcel createChangeUnlockParcel(Long masterKeyId, byte[] fingerprint,
|
||||
Passphrase newPassphrase) {
|
||||
return new AutoValue_ChangeUnlockParcel(masterKeyId, fingerprint, newPassphrase);
|
||||
}
|
||||
|
||||
public ChangeUnlockParcel(Long masterKeyId, byte[] fingerprint, Passphrase newPassphrase) {
|
||||
if (newPassphrase == null) {
|
||||
throw new AssertionError("newPassphrase must be non-null. THIS IS A BUG!");
|
||||
}
|
||||
|
||||
mMasterKeyId = masterKeyId;
|
||||
mFingerprint = fingerprint;
|
||||
mNewPassphrase = newPassphrase;
|
||||
public static ChangeUnlockParcel createUnLockParcelForNewKey(Passphrase newPassphrase) {
|
||||
return new AutoValue_ChangeUnlockParcel(null, null, newPassphrase);
|
||||
}
|
||||
|
||||
public ChangeUnlockParcel(Parcel source) {
|
||||
mMasterKeyId = source.readInt() != 0 ? source.readLong() : null;
|
||||
mFingerprint = source.createByteArray();
|
||||
mNewPassphrase = source.readParcelable(Passphrase.class.getClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel destination, int flags) {
|
||||
destination.writeInt(mMasterKeyId == null ? 0 : 1);
|
||||
if (mMasterKeyId != null) {
|
||||
destination.writeLong(mMasterKeyId);
|
||||
}
|
||||
destination.writeByteArray(mFingerprint);
|
||||
destination.writeParcelable(mNewPassphrase, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<ChangeUnlockParcel> CREATOR = new Creator<ChangeUnlockParcel>() {
|
||||
public ChangeUnlockParcel createFromParcel(final Parcel source) {
|
||||
return new ChangeUnlockParcel(source);
|
||||
}
|
||||
|
||||
public ChangeUnlockParcel[] newArray(final int size) {
|
||||
return new ChangeUnlockParcel[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String toString() {
|
||||
String out = "mMasterKeyId: " + mMasterKeyId + "\n";
|
||||
out += "passphrase (" + mNewPassphrase + ")";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,40 +19,17 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class ConsolidateInputParcel implements Parcelable {
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
public boolean mConsolidateRecovery;
|
||||
|
||||
public ConsolidateInputParcel(boolean consolidateRecovery) {
|
||||
mConsolidateRecovery = consolidateRecovery;
|
||||
@AutoValue
|
||||
public abstract class ConsolidateInputParcel implements Parcelable {
|
||||
public abstract boolean isStartFromRecovery();
|
||||
|
||||
public static ConsolidateInputParcel createConsolidateInputParcel(boolean consolidateRecovery) {
|
||||
return new AutoValue_ConsolidateInputParcel(consolidateRecovery);
|
||||
}
|
||||
|
||||
protected ConsolidateInputParcel(Parcel in) {
|
||||
mConsolidateRecovery = in.readByte() != 0x00;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeByte((byte) (mConsolidateRecovery ? 0x01 : 0x00));
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<ConsolidateInputParcel> CREATOR = new Parcelable.Creator<ConsolidateInputParcel>() {
|
||||
@Override
|
||||
public ConsolidateInputParcel createFromParcel(Parcel in) {
|
||||
return new ConsolidateInputParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsolidateInputParcel[] newArray(int size) {
|
||||
return new ConsolidateInputParcel[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -19,45 +19,25 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class DeleteKeyringParcel implements Parcelable {
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
public long[] mMasterKeyIds;
|
||||
public boolean mIsSecret;
|
||||
|
||||
public DeleteKeyringParcel(long[] masterKeyIds, boolean isSecret) {
|
||||
mMasterKeyIds = masterKeyIds;
|
||||
mIsSecret = isSecret;
|
||||
@AutoValue
|
||||
public abstract class DeleteKeyringParcel implements Parcelable {
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract long[] getMasterKeyIds();
|
||||
public abstract boolean isDeleteSecret();
|
||||
|
||||
|
||||
public static DeleteKeyringParcel createDeletePublicKeysParcel(long[] masterKeyIds) {
|
||||
return new AutoValue_DeleteKeyringParcel(masterKeyIds, false);
|
||||
}
|
||||
|
||||
protected DeleteKeyringParcel(Parcel in) {
|
||||
mIsSecret = in.readByte() != 0x00;
|
||||
mMasterKeyIds = in.createLongArray();
|
||||
public static DeleteKeyringParcel createDeleteSingleSecretKeyParcel(long masterKeyId) {
|
||||
return new AutoValue_DeleteKeyringParcel(new long[] { masterKeyId }, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeByte((byte) (mIsSecret ? 0x01 : 0x00));
|
||||
dest.writeLongArray(mMasterKeyIds);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<DeleteKeyringParcel> CREATOR = new Parcelable.Creator<DeleteKeyringParcel>() {
|
||||
@Override
|
||||
public DeleteKeyringParcel createFromParcel(Parcel in) {
|
||||
return new DeleteKeyringParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteKeyringParcel[] newArray(int size) {
|
||||
return new DeleteKeyringParcel[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -18,69 +18,31 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ImportKeyringParcel implements Parcelable {
|
||||
// If null, keys are expected to be read from a cache file in ImportExportOperations
|
||||
public ArrayList<ParcelableKeyRing> mKeyList;
|
||||
public ParcelableHkpKeyserver mKeyserver; // must be set if keys are to be imported from a keyserver
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
// If false, don't save the key, only return it as part of result
|
||||
public boolean mSkipSave = false;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||
|
||||
public ImportKeyringParcel(ArrayList<ParcelableKeyRing> keyList, ParcelableHkpKeyserver keyserver) {
|
||||
mKeyList = keyList;
|
||||
mKeyserver = keyserver;
|
||||
@AutoValue
|
||||
public abstract class ImportKeyringParcel implements Parcelable {
|
||||
@Nullable // If null, keys are expected to be read from a cache file in ImportExportOperations
|
||||
public abstract ArrayList<ParcelableKeyRing> getKeyList();
|
||||
@Nullable // must be set if keys are to be imported from a keyserver
|
||||
public abstract ParcelableHkpKeyserver getKeyserver();
|
||||
public abstract boolean isSkipSave();
|
||||
|
||||
public static ImportKeyringParcel createImportKeyringParcel(ArrayList<ParcelableKeyRing> keyList,
|
||||
ParcelableHkpKeyserver keyserver) {
|
||||
return new AutoValue_ImportKeyringParcel(keyList, keyserver, false);
|
||||
}
|
||||
|
||||
public ImportKeyringParcel(ArrayList<ParcelableKeyRing> keyList, ParcelableHkpKeyserver keyserver, boolean skipSave) {
|
||||
this(keyList, keyserver);
|
||||
mSkipSave = skipSave;
|
||||
public static ImportKeyringParcel createWithSkipSave(ArrayList<ParcelableKeyRing> keyList,
|
||||
ParcelableHkpKeyserver keyserver) {
|
||||
return new AutoValue_ImportKeyringParcel(keyList, keyserver, true);
|
||||
}
|
||||
|
||||
protected ImportKeyringParcel(Parcel in) {
|
||||
if (in.readByte() == 0x01) {
|
||||
mKeyList = new ArrayList<>();
|
||||
in.readList(mKeyList, ParcelableKeyRing.class.getClassLoader());
|
||||
} else {
|
||||
mKeyList = null;
|
||||
}
|
||||
mKeyserver = in.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
|
||||
mSkipSave = in.readInt() != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
if (mKeyList == null) {
|
||||
dest.writeByte((byte) (0x00));
|
||||
} else {
|
||||
dest.writeByte((byte) (0x01));
|
||||
dest.writeList(mKeyList);
|
||||
}
|
||||
dest.writeParcelable(mKeyserver, flags);
|
||||
dest.writeInt(mSkipSave ? 1 : 0);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<ImportKeyringParcel> CREATOR = new Parcelable.Creator<ImportKeyringParcel>() {
|
||||
@Override
|
||||
public ImportKeyringParcel createFromParcel(Parcel in) {
|
||||
return new ImportKeyringParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImportKeyringParcel[] newArray(int size) {
|
||||
return new ImportKeyringParcel[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -17,65 +17,24 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
|
||||
|
||||
|
||||
public class InputDataParcel implements Parcelable {
|
||||
@AutoValue
|
||||
public abstract class InputDataParcel implements Parcelable {
|
||||
public abstract Uri getInputUri();
|
||||
@Nullable
|
||||
public abstract PgpDecryptVerifyInputParcel getDecryptInput();
|
||||
public abstract boolean getMimeDecode(); // TODO static value - ditch this?
|
||||
|
||||
private Uri mInputUri;
|
||||
|
||||
private PgpDecryptVerifyInputParcel mDecryptInput;
|
||||
private boolean mMimeDecode = true; // TODO default to false
|
||||
|
||||
public InputDataParcel(Uri inputUri, PgpDecryptVerifyInputParcel decryptInput) {
|
||||
mInputUri = inputUri;
|
||||
mDecryptInput = decryptInput;
|
||||
public static InputDataParcel createInputDataParcel(Uri inputUri, PgpDecryptVerifyInputParcel decryptInput) {
|
||||
return new AutoValue_InputDataParcel(inputUri, decryptInput, true);
|
||||
}
|
||||
|
||||
InputDataParcel(Parcel source) {
|
||||
// we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
|
||||
mInputUri = source.readParcelable(getClass().getClassLoader());
|
||||
mDecryptInput = source.readParcelable(getClass().getClassLoader());
|
||||
mMimeDecode = source.readInt() != 0;
|
||||
}
|
||||
|
||||
public Uri getInputUri() {
|
||||
return mInputUri;
|
||||
}
|
||||
|
||||
public PgpDecryptVerifyInputParcel getDecryptInput() {
|
||||
return mDecryptInput;
|
||||
}
|
||||
|
||||
public boolean getMimeDecode() {
|
||||
return mMimeDecode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(mInputUri, 0);
|
||||
dest.writeParcelable(mDecryptInput, 0);
|
||||
dest.writeInt(mMimeDecode ? 1 : 0);
|
||||
}
|
||||
|
||||
public static final Creator<InputDataParcel> CREATOR = new Creator<InputDataParcel>() {
|
||||
public InputDataParcel createFromParcel(final Parcel source) {
|
||||
return new InputDataParcel(source);
|
||||
}
|
||||
|
||||
public InputDataParcel[] newArray(final int size) {
|
||||
return new InputDataParcel[size];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ public class KeyserverSyncAdapterService extends Service {
|
||||
}
|
||||
case ACTION_UPDATE_ALL: {
|
||||
// does not check for screen on/off
|
||||
asyncKeyUpdate(this, new CryptoInputParcel(), startId);
|
||||
asyncKeyUpdate(this, CryptoInputParcel.createCryptoInputParcel(), startId);
|
||||
// we depend on handleUpdateResult to call stopSelf when it is no longer necessary
|
||||
// for the intent to be redelivered
|
||||
return START_REDELIVER_INTENT;
|
||||
@@ -118,7 +118,7 @@ public class KeyserverSyncAdapterService extends Service {
|
||||
case ACTION_IGNORE_TOR: {
|
||||
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
manager.cancel(Constants.Notification.KEYSERVER_SYNC_FAIL_ORBOT);
|
||||
asyncKeyUpdate(this, new CryptoInputParcel(ParcelableProxy.getForNoProxy()),
|
||||
asyncKeyUpdate(this, CryptoInputParcel.createCryptoInputParcel(ParcelableProxy.getForNoProxy()),
|
||||
startId);
|
||||
// we depend on handleUpdateResult to call stopSelf when it is no longer necessary
|
||||
// for the intent to be redelivered
|
||||
@@ -324,7 +324,7 @@ public class KeyserverSyncAdapterService extends Service {
|
||||
ImportOperation importOp = new ImportOperation(context,
|
||||
KeyWritableRepository.createDatabaseReadWriteInteractor(context), null);
|
||||
return importOp.execute(
|
||||
new ImportKeyringParcel(keyList,
|
||||
ImportKeyringParcel.createImportKeyringParcel(keyList,
|
||||
Preferences.getPreferences(context).getPreferredKeyserver()),
|
||||
cryptoInputParcel
|
||||
);
|
||||
@@ -384,7 +384,7 @@ public class KeyserverSyncAdapterService extends Service {
|
||||
ImportKeyResult result =
|
||||
new ImportOperation(context, KeyWritableRepository.createDatabaseReadWriteInteractor(context), null, mCancelled)
|
||||
.execute(
|
||||
new ImportKeyringParcel(
|
||||
ImportKeyringParcel.createImportKeyringParcel(
|
||||
keyWrapper,
|
||||
Preferences.getPreferences(context)
|
||||
.getPreferredKeyserver()
|
||||
|
||||
@@ -19,48 +19,25 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class PromoteKeyringParcel implements Parcelable {
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
public long mKeyRingId;
|
||||
public byte[] mCardAid;
|
||||
public long[] mSubKeyIds;
|
||||
|
||||
public PromoteKeyringParcel(long keyRingId, byte[] cardAid, long[] subKeyIds) {
|
||||
mKeyRingId = keyRingId;
|
||||
mCardAid = cardAid;
|
||||
mSubKeyIds = subKeyIds;
|
||||
@AutoValue
|
||||
public abstract class PromoteKeyringParcel implements Parcelable {
|
||||
public abstract long getMasterKeyId();
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract byte[] getCardAid();
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract long[] getSubKeyIds();
|
||||
|
||||
public static PromoteKeyringParcel createPromoteKeyringParcel(long keyRingId, byte[] cardAid,
|
||||
@Nullable long[] subKeyIds) {
|
||||
return new AutoValue_PromoteKeyringParcel(keyRingId, cardAid, subKeyIds);
|
||||
}
|
||||
|
||||
protected PromoteKeyringParcel(Parcel in) {
|
||||
mKeyRingId = in.readLong();
|
||||
mCardAid = in.createByteArray();
|
||||
mSubKeyIds = in.createLongArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeLong(mKeyRingId);
|
||||
dest.writeByteArray(mCardAid);
|
||||
dest.writeLongArray(mSubKeyIds);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<PromoteKeyringParcel> CREATOR = new Parcelable.Creator<PromoteKeyringParcel>() {
|
||||
@Override
|
||||
public PromoteKeyringParcel createFromParcel(Parcel in) {
|
||||
return new PromoteKeyringParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PromoteKeyringParcel[] newArray(int size) {
|
||||
return new PromoteKeyringParcel[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -19,50 +19,22 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
|
||||
|
||||
public class RevokeKeyringParcel implements Parcelable {
|
||||
@AutoValue
|
||||
public abstract class RevokeKeyringParcel implements Parcelable {
|
||||
public abstract long getMasterKeyId();
|
||||
public abstract boolean isShouldUpload();
|
||||
@Nullable
|
||||
public abstract ParcelableHkpKeyserver getKeyserver();
|
||||
|
||||
final public long mMasterKeyId;
|
||||
final public boolean mUpload;
|
||||
final public ParcelableHkpKeyserver mKeyserver;
|
||||
|
||||
public RevokeKeyringParcel(long masterKeyId, boolean upload, ParcelableHkpKeyserver keyserver) {
|
||||
mMasterKeyId = masterKeyId;
|
||||
mUpload = upload;
|
||||
mKeyserver = keyserver;
|
||||
public static RevokeKeyringParcel createRevokeKeyringParcel(long masterKeyId, boolean upload,
|
||||
ParcelableHkpKeyserver keyserver) {
|
||||
return new AutoValue_RevokeKeyringParcel(masterKeyId, upload, keyserver);
|
||||
}
|
||||
|
||||
protected RevokeKeyringParcel(Parcel in) {
|
||||
mMasterKeyId = in.readLong();
|
||||
mUpload = in.readByte() != 0x00;
|
||||
mKeyserver = in.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeLong(mMasterKeyId);
|
||||
dest.writeByte((byte) (mUpload ? 0x01 : 0x00));
|
||||
dest.writeParcelable(mKeyserver, flags);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<RevokeKeyringParcel> CREATOR = new Parcelable.Creator<RevokeKeyringParcel>() {
|
||||
@Override
|
||||
public RevokeKeyringParcel createFromParcel(Parcel in) {
|
||||
return new RevokeKeyringParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RevokeKeyringParcel[] newArray(int size) {
|
||||
return new RevokeKeyringParcel[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -18,15 +18,19 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
|
||||
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
/**
|
||||
* This class is a a transferable representation for a collection of changes
|
||||
@@ -43,306 +47,247 @@ import java.util.ArrayList;
|
||||
* error in any included operation (for example revocation of a non-existent
|
||||
* subkey) will cause the operation as a whole to fail.
|
||||
*/
|
||||
public class SaveKeyringParcel implements Parcelable {
|
||||
@AutoValue
|
||||
public abstract class SaveKeyringParcel implements Parcelable {
|
||||
|
||||
// the master key id to be edited. if this is null, a new one will be created
|
||||
public Long mMasterKeyId;
|
||||
@Nullable
|
||||
public abstract Long getMasterKeyId();
|
||||
// the key fingerprint, for safety. MUST be null for a new key.
|
||||
public byte[] mFingerprint;
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract byte[] getFingerprint();
|
||||
|
||||
public ArrayList<String> mAddUserIds;
|
||||
public ArrayList<WrappedUserAttribute> mAddUserAttribute;
|
||||
public ArrayList<SubkeyAdd> mAddSubKeys;
|
||||
public abstract List<String> getAddUserIds();
|
||||
public abstract List<WrappedUserAttribute> getAddUserAttribute();
|
||||
public abstract List<SubkeyAdd> getAddSubKeys();
|
||||
|
||||
public ArrayList<SubkeyChange> mChangeSubKeys;
|
||||
public String mChangePrimaryUserId;
|
||||
public abstract List<SubkeyChange> getChangeSubKeys();
|
||||
@Nullable
|
||||
public abstract String getChangePrimaryUserId();
|
||||
|
||||
public ArrayList<String> mRevokeUserIds;
|
||||
public ArrayList<Long> mRevokeSubKeys;
|
||||
public abstract List<String> getRevokeUserIds();
|
||||
public abstract List<Long> getRevokeSubKeys();
|
||||
|
||||
// if these are non-null, PINs will be changed on the token
|
||||
public Passphrase mSecurityTokenPin;
|
||||
public Passphrase mSecurityTokenAdminPin;
|
||||
@Nullable
|
||||
public abstract Passphrase getSecurityTokenPin();
|
||||
@Nullable
|
||||
public abstract Passphrase getSecurityTokenAdminPin();
|
||||
|
||||
// private because they have to be set together with setUpdateOptions
|
||||
private boolean mUpload;
|
||||
private boolean mUploadAtomic;
|
||||
private ParcelableHkpKeyserver mKeyserver;
|
||||
public abstract boolean isShouldUpload();
|
||||
public abstract boolean isShouldUploadAtomic();
|
||||
@Nullable
|
||||
public abstract ParcelableHkpKeyserver getUploadKeyserver();
|
||||
|
||||
// private because we have to set other details like key id
|
||||
private ChangeUnlockParcel mNewUnlock;
|
||||
@Nullable
|
||||
public abstract ChangeUnlockParcel getNewUnlock();
|
||||
|
||||
public SaveKeyringParcel() {
|
||||
reset();
|
||||
public static Builder buildNewKeyringParcel() {
|
||||
return new AutoValue_SaveKeyringParcel.Builder()
|
||||
.setShouldUpload(false)
|
||||
.setShouldUploadAtomic(false);
|
||||
}
|
||||
|
||||
public SaveKeyringParcel(long masterKeyId, byte[] fingerprint) {
|
||||
this();
|
||||
mMasterKeyId = masterKeyId;
|
||||
mFingerprint = fingerprint;
|
||||
public static Builder buildChangeKeyringParcel(long masterKeyId, byte[] fingerprint) {
|
||||
return buildNewKeyringParcel()
|
||||
.setMasterKeyId(masterKeyId)
|
||||
.setFingerprint(fingerprint);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mNewUnlock = null;
|
||||
mAddUserIds = new ArrayList<>();
|
||||
mAddUserAttribute = new ArrayList<>();
|
||||
mAddSubKeys = new ArrayList<>();
|
||||
mChangePrimaryUserId = null;
|
||||
mChangeSubKeys = new ArrayList<>();
|
||||
mRevokeUserIds = new ArrayList<>();
|
||||
mRevokeSubKeys = new ArrayList<>();
|
||||
mSecurityTokenPin = null;
|
||||
mSecurityTokenAdminPin = null;
|
||||
mUpload = false;
|
||||
mUploadAtomic = false;
|
||||
mKeyserver = null;
|
||||
abstract Builder toBuilder();
|
||||
|
||||
public static Builder buildUpon(SaveKeyringParcel saveKeyringParcel) {
|
||||
SaveKeyringParcel.Builder builder = saveKeyringParcel.toBuilder();
|
||||
builder.addUserIds.addAll(saveKeyringParcel.getAddUserIds());
|
||||
builder.revokeUserIds.addAll(saveKeyringParcel.getRevokeUserIds());
|
||||
builder.addUserAttribute.addAll(saveKeyringParcel.getAddUserAttribute());
|
||||
builder.addSubKeys.addAll(saveKeyringParcel.getAddSubKeys());
|
||||
builder.changeSubKeys.addAll(saveKeyringParcel.getChangeSubKeys());
|
||||
builder.revokeSubKeys.addAll(saveKeyringParcel.getRevokeSubKeys());
|
||||
return builder;
|
||||
}
|
||||
|
||||
public void setUpdateOptions(boolean upload, boolean uploadAtomic, ParcelableHkpKeyserver keyserver) {
|
||||
mUpload = upload;
|
||||
mUploadAtomic = uploadAtomic;
|
||||
mKeyserver = keyserver;
|
||||
}
|
||||
@AutoValue.Builder
|
||||
public static abstract class Builder {
|
||||
private ArrayList<String> addUserIds = new ArrayList<>();
|
||||
private ArrayList<String> revokeUserIds = new ArrayList<>();
|
||||
private ArrayList<WrappedUserAttribute> addUserAttribute = new ArrayList<>();
|
||||
private ArrayList<SubkeyAdd> addSubKeys = new ArrayList<>();
|
||||
private ArrayList<SubkeyChange> changeSubKeys = new ArrayList<>();
|
||||
private ArrayList<Long> revokeSubKeys = new ArrayList<>();
|
||||
|
||||
public void setNewUnlock(ChangeUnlockParcel parcel) {
|
||||
mNewUnlock = parcel;
|
||||
}
|
||||
|
||||
public ChangeUnlockParcel getChangeUnlockParcel() {
|
||||
if(mNewUnlock != null) {
|
||||
mNewUnlock.mMasterKeyId = mMasterKeyId;
|
||||
mNewUnlock.mFingerprint = mFingerprint;
|
||||
public abstract Builder setChangePrimaryUserId(String changePrimaryUserId);
|
||||
public abstract Builder setSecurityTokenPin(Passphrase securityTokenPin);
|
||||
public abstract Builder setSecurityTokenAdminPin(Passphrase securityTokenAdminPin);
|
||||
public abstract Builder setNewUnlock(ChangeUnlockParcel newUnlock);
|
||||
|
||||
public abstract Long getMasterKeyId();
|
||||
public abstract byte[] getFingerprint();
|
||||
public abstract String getChangePrimaryUserId();
|
||||
|
||||
|
||||
public ArrayList<SubkeyAdd> getMutableAddSubKeys() {
|
||||
return addSubKeys;
|
||||
}
|
||||
return mNewUnlock;
|
||||
}
|
||||
|
||||
public boolean isUpload() {
|
||||
return mUpload;
|
||||
}
|
||||
|
||||
public boolean isUploadAtomic() {
|
||||
return mUploadAtomic;
|
||||
}
|
||||
|
||||
public ParcelableHkpKeyserver getUploadKeyserver() {
|
||||
return mKeyserver;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return isRestrictedOnly() && mChangeSubKeys.isEmpty();
|
||||
}
|
||||
|
||||
/** Returns true iff this parcel does not contain any operations which require a passphrase. */
|
||||
public boolean isRestrictedOnly() {
|
||||
if (mNewUnlock != null || !mAddUserIds.isEmpty() || !mAddUserAttribute.isEmpty()
|
||||
|| !mAddSubKeys.isEmpty() || mChangePrimaryUserId != null || !mRevokeUserIds.isEmpty()
|
||||
|| !mRevokeSubKeys.isEmpty()) {
|
||||
return false;
|
||||
public ArrayList<String> getMutableAddUserIds() {
|
||||
return addUserIds;
|
||||
}
|
||||
public ArrayList<Long> getMutableRevokeSubKeys() {
|
||||
return revokeSubKeys;
|
||||
}
|
||||
public ArrayList<String> getMutableRevokeUserIds() {
|
||||
return revokeUserIds;
|
||||
}
|
||||
|
||||
for (SubkeyChange change : mChangeSubKeys) {
|
||||
if (change.mRecertify || change.mFlags != null || change.mExpiry != null
|
||||
|| change.mMoveKeyToSecurityToken) {
|
||||
return false;
|
||||
abstract Builder setMasterKeyId(Long masterKeyId);
|
||||
abstract Builder setFingerprint(byte[] fingerprint);
|
||||
abstract Builder setAddUserIds(List<String> addUserIds);
|
||||
abstract Builder setAddUserAttribute(List<WrappedUserAttribute> addUserAttribute);
|
||||
abstract Builder setAddSubKeys(List<SubkeyAdd> addSubKeys);
|
||||
abstract Builder setChangeSubKeys(List<SubkeyChange> changeSubKeys);
|
||||
abstract Builder setRevokeUserIds(List<String> revokeUserIds);
|
||||
abstract Builder setRevokeSubKeys(List<Long> revokeSubKeys);
|
||||
abstract Builder setShouldUpload(boolean upload);
|
||||
abstract Builder setShouldUploadAtomic(boolean uploadAtomic);
|
||||
abstract Builder setUploadKeyserver(ParcelableHkpKeyserver keyserver);
|
||||
|
||||
public void setUpdateOptions(boolean upload, boolean uploadAtomic, ParcelableHkpKeyserver keyserver) {
|
||||
setShouldUpload(upload);
|
||||
setShouldUploadAtomic(uploadAtomic);
|
||||
setUploadKeyserver(keyserver);
|
||||
}
|
||||
|
||||
public void addSubkeyAdd(SubkeyAdd subkeyAdd) {
|
||||
addSubKeys.add(subkeyAdd);
|
||||
}
|
||||
|
||||
public void addUserId(String userId) {
|
||||
addUserIds.add(userId);
|
||||
}
|
||||
|
||||
public void addRevokeSubkey(long masterKeyId) {
|
||||
revokeSubKeys.add(masterKeyId);
|
||||
}
|
||||
|
||||
public void removeRevokeSubkey(long keyId) {
|
||||
revokeSubKeys.remove(keyId);
|
||||
}
|
||||
|
||||
public void addRevokeUserId(String userId) {
|
||||
revokeUserIds.add(userId);
|
||||
}
|
||||
|
||||
public void removeRevokeUserId(String userId) {
|
||||
revokeUserIds.remove(userId);
|
||||
}
|
||||
|
||||
public void addOrReplaceSubkeyChange(SubkeyChange newChange) {
|
||||
SubkeyChange foundSubkeyChange = getSubkeyChange(newChange.getSubKeyId());
|
||||
|
||||
if (foundSubkeyChange != null) {
|
||||
changeSubKeys.remove(foundSubkeyChange);
|
||||
}
|
||||
changeSubKeys.add(newChange);
|
||||
}
|
||||
|
||||
return true;
|
||||
public void removeSubkeyChange(SubkeyChange change) {
|
||||
changeSubKeys.remove(change);
|
||||
}
|
||||
|
||||
public SubkeyChange getSubkeyChange(long keyId) {
|
||||
if (changeSubKeys == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (SubkeyChange subkeyChange : changeSubKeys) {
|
||||
if (subkeyChange.getSubKeyId() == keyId) {
|
||||
return subkeyChange;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addUserAttribute(WrappedUserAttribute ua) {
|
||||
addUserAttribute.add(ua);
|
||||
}
|
||||
|
||||
abstract SaveKeyringParcel autoBuild();
|
||||
|
||||
public SaveKeyringParcel build() {
|
||||
setAddUserAttribute(Collections.unmodifiableList(addUserAttribute));
|
||||
setRevokeSubKeys(Collections.unmodifiableList(revokeSubKeys));
|
||||
setRevokeUserIds(Collections.unmodifiableList(revokeUserIds));
|
||||
setAddSubKeys(Collections.unmodifiableList(addSubKeys));
|
||||
setAddUserIds(Collections.unmodifiableList(addUserIds));
|
||||
setChangeSubKeys(Collections.unmodifiableList(changeSubKeys));
|
||||
|
||||
return autoBuild();
|
||||
}
|
||||
}
|
||||
|
||||
// performance gain for using Parcelable here would probably be negligible,
|
||||
// use Serializable instead.
|
||||
public static class SubkeyAdd implements Serializable {
|
||||
public Algorithm mAlgorithm;
|
||||
public Integer mKeySize;
|
||||
public Curve mCurve;
|
||||
public int mFlags;
|
||||
public Long mExpiry;
|
||||
@AutoValue
|
||||
public abstract static class SubkeyAdd implements Serializable {
|
||||
public abstract Algorithm getAlgorithm();
|
||||
@Nullable
|
||||
public abstract Integer getKeySize();
|
||||
@Nullable
|
||||
public abstract Curve getCurve();
|
||||
public abstract int getFlags();
|
||||
@Nullable
|
||||
public abstract Long getExpiry();
|
||||
|
||||
public SubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags, Long expiry) {
|
||||
mAlgorithm = algorithm;
|
||||
mKeySize = keySize;
|
||||
mCurve = curve;
|
||||
mFlags = flags;
|
||||
mExpiry = expiry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String out = "mAlgorithm: " + mAlgorithm + ", ";
|
||||
out += "mKeySize: " + mKeySize + ", ";
|
||||
out += "mCurve: " + mCurve + ", ";
|
||||
out += "mFlags: " + mFlags;
|
||||
out += "mExpiry: " + mExpiry;
|
||||
|
||||
return out;
|
||||
public static SubkeyAdd createSubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags,
|
||||
Long expiry) {
|
||||
return new AutoValue_SaveKeyringParcel_SubkeyAdd(algorithm, keySize, curve, flags, expiry);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SubkeyChange implements Serializable {
|
||||
public final long mKeyId;
|
||||
public Integer mFlags;
|
||||
@AutoValue
|
||||
public abstract static class SubkeyChange implements Serializable {
|
||||
public abstract long getSubKeyId();
|
||||
@Nullable
|
||||
public abstract Integer getFlags();
|
||||
// this is a long unix timestamp, in seconds (NOT MILLISECONDS!)
|
||||
public Long mExpiry;
|
||||
@Nullable
|
||||
public abstract Long getExpiry();
|
||||
// if this flag is true, the key will be recertified even if all above
|
||||
// values are no-ops
|
||||
public boolean mRecertify;
|
||||
public abstract boolean getRecertify();
|
||||
// if this flag is true, the subkey should be changed to a stripped key
|
||||
public boolean mDummyStrip;
|
||||
public abstract boolean getDummyStrip();
|
||||
// if this flag is true, the subkey should be moved to a security token
|
||||
public boolean mMoveKeyToSecurityToken;
|
||||
public abstract boolean getMoveKeyToSecurityToken();
|
||||
// if this is non-null, the subkey will be changed to a divert-to-card
|
||||
// (security token) key for the given serial number
|
||||
public byte[] mSecurityTokenSerialNo;
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract byte[] getSecurityTokenSerialNo();
|
||||
|
||||
public SubkeyChange(long keyId) {
|
||||
mKeyId = keyId;
|
||||
public static SubkeyChange createRecertifyChange(long keyId, boolean recertify) {
|
||||
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, recertify, false, false, null);
|
||||
}
|
||||
|
||||
public SubkeyChange(long keyId, boolean recertify) {
|
||||
mKeyId = keyId;
|
||||
mRecertify = recertify;
|
||||
public static SubkeyChange createFlagsOrExpiryChange(long keyId, Integer flags, Long expiry) {
|
||||
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, flags, expiry, false, false, false, null);
|
||||
}
|
||||
|
||||
public SubkeyChange(long keyId, Integer flags, Long expiry) {
|
||||
mKeyId = keyId;
|
||||
mFlags = flags;
|
||||
mExpiry = expiry;
|
||||
public static SubkeyChange createStripChange(long keyId) {
|
||||
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, false, true, false, null);
|
||||
}
|
||||
|
||||
public SubkeyChange(long keyId, boolean dummyStrip, boolean moveKeyToSecurityToken) {
|
||||
this(keyId, null, null);
|
||||
|
||||
// these flags are mutually exclusive!
|
||||
if (dummyStrip && moveKeyToSecurityToken) {
|
||||
throw new AssertionError(
|
||||
"cannot set strip and moveKeyToSecurityToken" +
|
||||
" flags at the same time - this is a bug!");
|
||||
}
|
||||
mDummyStrip = dummyStrip;
|
||||
mMoveKeyToSecurityToken = moveKeyToSecurityToken;
|
||||
public static SubkeyChange createMoveToSecurityTokenChange(long keyId) {
|
||||
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, false, false, true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String out = "mKeyId: " + mKeyId + ", ";
|
||||
out += "mFlags: " + mFlags + ", ";
|
||||
out += "mExpiry: " + mExpiry + ", ";
|
||||
out += "mDummyStrip: " + mDummyStrip + ", ";
|
||||
out += "mMoveKeyToSecurityToken: " + mMoveKeyToSecurityToken + ", ";
|
||||
out += "mSecurityTokenSerialNo: [" + (mSecurityTokenSerialNo == null ? 0 : mSecurityTokenSerialNo.length) + " bytes]";
|
||||
|
||||
return out;
|
||||
public static SubkeyChange createSecurityTokenSerialNo(long keyId, byte[] securityTokenSerialNo) {
|
||||
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, false, false, false, securityTokenSerialNo);
|
||||
}
|
||||
}
|
||||
|
||||
public SubkeyChange getSubkeyChange(long keyId) {
|
||||
for (SubkeyChange subkeyChange : mChangeSubKeys) {
|
||||
if (subkeyChange.mKeyId == keyId) {
|
||||
return subkeyChange;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public SubkeyChange getOrCreateSubkeyChange(long keyId) {
|
||||
SubkeyChange foundSubkeyChange = getSubkeyChange(keyId);
|
||||
if (foundSubkeyChange != null) {
|
||||
return foundSubkeyChange;
|
||||
} else {
|
||||
// else, create a new one
|
||||
SubkeyChange newSubkeyChange = new SubkeyChange(keyId);
|
||||
mChangeSubKeys.add(newSubkeyChange);
|
||||
return newSubkeyChange;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // we verify the reads against writes in writeToParcel
|
||||
public SaveKeyringParcel(Parcel source) {
|
||||
mMasterKeyId = source.readInt() != 0 ? source.readLong() : null;
|
||||
mFingerprint = source.createByteArray();
|
||||
|
||||
mNewUnlock = source.readParcelable(getClass().getClassLoader());
|
||||
|
||||
mAddUserIds = source.createStringArrayList();
|
||||
mAddUserAttribute = (ArrayList<WrappedUserAttribute>) source.readSerializable();
|
||||
mAddSubKeys = (ArrayList<SubkeyAdd>) source.readSerializable();
|
||||
|
||||
mChangeSubKeys = (ArrayList<SubkeyChange>) source.readSerializable();
|
||||
mChangePrimaryUserId = source.readString();
|
||||
|
||||
mRevokeUserIds = source.createStringArrayList();
|
||||
mRevokeSubKeys = (ArrayList<Long>) source.readSerializable();
|
||||
|
||||
mSecurityTokenPin = source.readParcelable(Passphrase.class.getClassLoader());
|
||||
mSecurityTokenAdminPin = source.readParcelable(Passphrase.class.getClassLoader());
|
||||
|
||||
mUpload = source.readByte() != 0;
|
||||
mUploadAtomic = source.readByte() != 0;
|
||||
mKeyserver = source.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel destination, int flags) {
|
||||
destination.writeInt(mMasterKeyId == null ? 0 : 1);
|
||||
if (mMasterKeyId != null) {
|
||||
destination.writeLong(mMasterKeyId);
|
||||
}
|
||||
destination.writeByteArray(mFingerprint);
|
||||
|
||||
// yes, null values are ok for parcelables
|
||||
destination.writeParcelable(mNewUnlock, flags);
|
||||
|
||||
destination.writeStringList(mAddUserIds);
|
||||
destination.writeSerializable(mAddUserAttribute);
|
||||
destination.writeSerializable(mAddSubKeys);
|
||||
|
||||
destination.writeSerializable(mChangeSubKeys);
|
||||
destination.writeString(mChangePrimaryUserId);
|
||||
|
||||
destination.writeStringList(mRevokeUserIds);
|
||||
destination.writeSerializable(mRevokeSubKeys);
|
||||
|
||||
destination.writeParcelable(mSecurityTokenPin, flags);
|
||||
destination.writeParcelable(mSecurityTokenAdminPin, flags);
|
||||
|
||||
destination.writeByte((byte) (mUpload ? 1 : 0));
|
||||
destination.writeByte((byte) (mUploadAtomic ? 1 : 0));
|
||||
destination.writeParcelable(mKeyserver, flags);
|
||||
}
|
||||
|
||||
public static final Creator<SaveKeyringParcel> CREATOR = new Creator<SaveKeyringParcel>() {
|
||||
public SaveKeyringParcel createFromParcel(final Parcel source) {
|
||||
return new SaveKeyringParcel(source);
|
||||
}
|
||||
|
||||
public SaveKeyringParcel[] newArray(final int size) {
|
||||
return new SaveKeyringParcel[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String out = "mMasterKeyId: " + mMasterKeyId + "\n";
|
||||
out += "mNewUnlock: " + mNewUnlock + "\n";
|
||||
out += "mAddUserIds: " + mAddUserIds + "\n";
|
||||
out += "mAddUserAttribute: " + mAddUserAttribute + "\n";
|
||||
out += "mAddSubKeys: " + mAddSubKeys + "\n";
|
||||
out += "mChangeSubKeys: " + mChangeSubKeys + "\n";
|
||||
out += "mChangePrimaryUserId: " + mChangePrimaryUserId + "\n";
|
||||
out += "mRevokeUserIds: " + mRevokeUserIds + "\n";
|
||||
out += "mRevokeSubKeys: " + mRevokeSubKeys + "\n";
|
||||
out += "mSecurityTokenPin: " + mSecurityTokenPin + "\n";
|
||||
out += "mSecurityTokenAdminPin: " + mSecurityTokenAdminPin;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// All supported algorithms
|
||||
public enum Algorithm {
|
||||
RSA, DSA, ELGAMAL, ECDSA, ECDH
|
||||
@@ -357,7 +302,4 @@ public class SaveKeyringParcel implements Parcelable {
|
||||
// (adding support would be trivial though -> JcaPGPKeyConverter.java:190)
|
||||
// BRAINPOOL_P256, BRAINPOOL_P384, BRAINPOOL_P512
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,62 +20,29 @@
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
|
||||
|
||||
@AutoValue
|
||||
public abstract class UploadKeyringParcel implements Parcelable {
|
||||
public abstract ParcelableHkpKeyserver getKeyserver();
|
||||
@Nullable
|
||||
public abstract Long getMasterKeyId();
|
||||
@Nullable
|
||||
@SuppressWarnings("mutable")
|
||||
public abstract byte[] getUncachedKeyringBytes();
|
||||
|
||||
public class UploadKeyringParcel implements Parcelable {
|
||||
public ParcelableHkpKeyserver mKeyserver;
|
||||
|
||||
public final Long mMasterKeyId;
|
||||
public final byte[] mUncachedKeyringBytes;
|
||||
|
||||
public UploadKeyringParcel(ParcelableHkpKeyserver keyserver, long masterKeyId) {
|
||||
mKeyserver = keyserver;
|
||||
mMasterKeyId = masterKeyId;
|
||||
mUncachedKeyringBytes = null;
|
||||
public static UploadKeyringParcel createWithKeyId(ParcelableHkpKeyserver keyserver, long masterKeyId) {
|
||||
return new AutoValue_UploadKeyringParcel(keyserver, masterKeyId, null);
|
||||
}
|
||||
|
||||
public UploadKeyringParcel(ParcelableHkpKeyserver keyserver, byte[] uncachedKeyringBytes) {
|
||||
mKeyserver = keyserver;
|
||||
mMasterKeyId = null;
|
||||
mUncachedKeyringBytes = uncachedKeyringBytes;
|
||||
public static UploadKeyringParcel createWithKeyringBytes(ParcelableHkpKeyserver keyserver,
|
||||
@NonNull byte[] uncachedKeyringBytes) {
|
||||
return new AutoValue_UploadKeyringParcel(keyserver, null, uncachedKeyringBytes);
|
||||
}
|
||||
|
||||
protected UploadKeyringParcel(Parcel in) {
|
||||
mKeyserver = in.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
|
||||
mMasterKeyId = in.readInt() != 0 ? in.readLong() : null;
|
||||
mUncachedKeyringBytes = in.createByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(mKeyserver, flags);
|
||||
if (mMasterKeyId != null) {
|
||||
dest.writeInt(1);
|
||||
dest.writeLong(mMasterKeyId);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
dest.writeByteArray(mUncachedKeyringBytes);
|
||||
}
|
||||
|
||||
public static final Creator<UploadKeyringParcel> CREATOR = new Creator<UploadKeyringParcel>() {
|
||||
@Override
|
||||
public UploadKeyringParcel createFromParcel(Parcel in) {
|
||||
return new UploadKeyringParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadKeyringParcel[] newArray(int size) {
|
||||
return new UploadKeyringParcel[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -19,181 +19,128 @@ package org.sufficientlysecure.keychain.service.input;
|
||||
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.ryanharter.auto.value.parcel.ParcelAdapter;
|
||||
import org.sufficientlysecure.keychain.util.ByteMapParcelAdapter;
|
||||
import org.sufficientlysecure.keychain.util.ParcelableProxy;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
/**
|
||||
* This is a base class for the input of crypto operations.
|
||||
*/
|
||||
public class CryptoInputParcel implements Parcelable {
|
||||
@AutoValue
|
||||
public abstract class CryptoInputParcel implements Parcelable {
|
||||
@Nullable
|
||||
public abstract Date getSignatureTime();
|
||||
@Nullable
|
||||
public abstract Passphrase getPassphrase();
|
||||
public abstract boolean isCachePassphrase();
|
||||
|
||||
private Date mSignatureTime;
|
||||
private boolean mHasSignature;
|
||||
public boolean hasPassphrase() {
|
||||
return getPassphrase() != null;
|
||||
}
|
||||
|
||||
public Passphrase mPassphrase;
|
||||
// used to supply an explicit proxy to operations that require it
|
||||
// this is not final so it can be added to an existing CryptoInputParcel
|
||||
// (e.g) CertifyOperation with upload might require both passphrase and orbot to be enabled
|
||||
private ParcelableProxy mParcelableProxy;
|
||||
|
||||
// specifies whether passphrases should be cached
|
||||
public boolean mCachePassphrase = true;
|
||||
@Nullable
|
||||
public abstract ParcelableProxy getParcelableProxy();
|
||||
|
||||
// this map contains both decrypted session keys and signed hashes to be
|
||||
// used in the crypto operation described by this parcel.
|
||||
private HashMap<ByteBuffer, byte[]> mCryptoData = new HashMap<>();
|
||||
@ParcelAdapter(ByteMapParcelAdapter.class)
|
||||
public abstract Map<ByteBuffer, byte[]> getCryptoData();
|
||||
|
||||
public CryptoInputParcel() {
|
||||
mSignatureTime = null;
|
||||
mPassphrase = null;
|
||||
mCachePassphrase = true;
|
||||
|
||||
public static CryptoInputParcel createCryptoInputParcel() {
|
||||
return new AutoValue_CryptoInputParcel(null, null, true, null, Collections.<ByteBuffer,byte[]>emptyMap());
|
||||
}
|
||||
|
||||
public CryptoInputParcel(Date signatureTime, Passphrase passphrase) {
|
||||
mHasSignature = true;
|
||||
mSignatureTime = signatureTime == null ? new Date() : signatureTime;
|
||||
mPassphrase = passphrase;
|
||||
mCachePassphrase = true;
|
||||
}
|
||||
|
||||
public CryptoInputParcel(Passphrase passphrase) {
|
||||
mPassphrase = passphrase;
|
||||
mCachePassphrase = true;
|
||||
}
|
||||
|
||||
public CryptoInputParcel(Date signatureTime) {
|
||||
mHasSignature = true;
|
||||
mSignatureTime = signatureTime == null ? new Date() : signatureTime;
|
||||
mPassphrase = null;
|
||||
mCachePassphrase = true;
|
||||
}
|
||||
|
||||
public CryptoInputParcel(ParcelableProxy parcelableProxy) {
|
||||
this();
|
||||
mParcelableProxy = parcelableProxy;
|
||||
}
|
||||
|
||||
public CryptoInputParcel(Date signatureTime, boolean cachePassphrase) {
|
||||
mHasSignature = true;
|
||||
mSignatureTime = signatureTime == null ? new Date() : signatureTime;
|
||||
mPassphrase = null;
|
||||
mCachePassphrase = cachePassphrase;
|
||||
}
|
||||
|
||||
public CryptoInputParcel(boolean cachePassphrase) {
|
||||
mCachePassphrase = cachePassphrase;
|
||||
}
|
||||
|
||||
protected CryptoInputParcel(Parcel source) {
|
||||
mHasSignature = source.readByte() != 0;
|
||||
if (mHasSignature) {
|
||||
mSignatureTime = new Date(source.readLong());
|
||||
public static CryptoInputParcel createCryptoInputParcel(Date signatureTime, Passphrase passphrase) {
|
||||
if (signatureTime == null) {
|
||||
signatureTime = new Date();
|
||||
}
|
||||
mPassphrase = source.readParcelable(getClass().getClassLoader());
|
||||
mParcelableProxy = source.readParcelable(getClass().getClassLoader());
|
||||
mCachePassphrase = source.readByte() != 0;
|
||||
return new AutoValue_CryptoInputParcel(signatureTime, passphrase, true, null,
|
||||
Collections.<ByteBuffer,byte[]>emptyMap());
|
||||
}
|
||||
|
||||
{
|
||||
int count = source.readInt();
|
||||
mCryptoData = new HashMap<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
byte[] key = source.createByteArray();
|
||||
byte[] value = source.createByteArray();
|
||||
mCryptoData.put(ByteBuffer.wrap(key), value);
|
||||
}
|
||||
public static CryptoInputParcel createCryptoInputParcel(Passphrase passphrase) {
|
||||
return new AutoValue_CryptoInputParcel(null, passphrase, true, null, Collections.<ByteBuffer,byte[]>emptyMap());
|
||||
}
|
||||
|
||||
public static CryptoInputParcel createCryptoInputParcel(Date signatureTime) {
|
||||
if (signatureTime == null) {
|
||||
signatureTime = new Date();
|
||||
}
|
||||
|
||||
return new AutoValue_CryptoInputParcel(signatureTime, null, true, null,
|
||||
Collections.<ByteBuffer,byte[]>emptyMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
public static CryptoInputParcel createCryptoInputParcel(ParcelableProxy parcelableProxy) {
|
||||
return new AutoValue_CryptoInputParcel(null, null, true, parcelableProxy, new HashMap<ByteBuffer,byte[]>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeByte((byte) (mHasSignature ? 1 : 0));
|
||||
if (mHasSignature) {
|
||||
dest.writeLong(mSignatureTime.getTime());
|
||||
}
|
||||
dest.writeParcelable(mPassphrase, 0);
|
||||
dest.writeParcelable(mParcelableProxy, 0);
|
||||
dest.writeByte((byte) (mCachePassphrase ? 1 : 0));
|
||||
|
||||
dest.writeInt(mCryptoData.size());
|
||||
for (HashMap.Entry<ByteBuffer, byte[]> entry : mCryptoData.entrySet()) {
|
||||
dest.writeByteArray(entry.getKey().array());
|
||||
dest.writeByteArray(entry.getValue());
|
||||
public static CryptoInputParcel createCryptoInputParcel(Date signatureTime, boolean cachePassphrase) {
|
||||
if (signatureTime == null) {
|
||||
signatureTime = new Date();
|
||||
}
|
||||
return new AutoValue_CryptoInputParcel(signatureTime, null, cachePassphrase, null,
|
||||
new HashMap<ByteBuffer,byte[]>());
|
||||
}
|
||||
|
||||
public void addParcelableProxy(ParcelableProxy parcelableProxy) {
|
||||
mParcelableProxy = parcelableProxy;
|
||||
public static CryptoInputParcel createCryptoInputParcel(boolean cachePassphrase) {
|
||||
return new AutoValue_CryptoInputParcel(null, null, cachePassphrase, null, new HashMap<ByteBuffer,byte[]>());
|
||||
}
|
||||
|
||||
public void addSignatureTime(Date signatureTime) {
|
||||
mSignatureTime = signatureTime;
|
||||
// TODO get rid of this!
|
||||
@CheckResult
|
||||
public CryptoInputParcel withCryptoData(byte[] hash, byte[] signedHash) {
|
||||
Map<ByteBuffer,byte[]> newCryptoData = new HashMap<>(getCryptoData());
|
||||
newCryptoData.put(ByteBuffer.wrap(hash), signedHash);
|
||||
newCryptoData = Collections.unmodifiableMap(newCryptoData);
|
||||
|
||||
return new AutoValue_CryptoInputParcel(getSignatureTime(), getPassphrase(), isCachePassphrase(),
|
||||
getParcelableProxy(), newCryptoData);
|
||||
}
|
||||
|
||||
public void addCryptoData(byte[] hash, byte[] signedHash) {
|
||||
mCryptoData.put(ByteBuffer.wrap(hash), signedHash);
|
||||
@CheckResult
|
||||
public CryptoInputParcel withCryptoData(Map<ByteBuffer, byte[]> cachedSessionKeys) {
|
||||
Map<ByteBuffer,byte[]> newCryptoData = new HashMap<>(getCryptoData());
|
||||
newCryptoData.putAll(cachedSessionKeys);
|
||||
newCryptoData = Collections.unmodifiableMap(newCryptoData);
|
||||
|
||||
return new AutoValue_CryptoInputParcel(getSignatureTime(), getPassphrase(), isCachePassphrase(),
|
||||
getParcelableProxy(), newCryptoData);
|
||||
}
|
||||
|
||||
public void addCryptoData(Map<ByteBuffer, byte[]> cachedSessionKeys) {
|
||||
mCryptoData.putAll(cachedSessionKeys);
|
||||
|
||||
@CheckResult
|
||||
public CryptoInputParcel withPassphrase(Passphrase passphrase) {
|
||||
return new AutoValue_CryptoInputParcel(getSignatureTime(), passphrase, isCachePassphrase(),
|
||||
getParcelableProxy(), getCryptoData());
|
||||
}
|
||||
|
||||
public ParcelableProxy getParcelableProxy() {
|
||||
return mParcelableProxy;
|
||||
@CheckResult
|
||||
public CryptoInputParcel withNoCachePassphrase() {
|
||||
return new AutoValue_CryptoInputParcel(getSignatureTime(), getPassphrase(), false, getParcelableProxy(),
|
||||
getCryptoData());
|
||||
}
|
||||
|
||||
public Map<ByteBuffer, byte[]> getCryptoData() {
|
||||
return mCryptoData;
|
||||
@CheckResult
|
||||
public CryptoInputParcel withSignatureTime(Date signatureTime) {
|
||||
return new AutoValue_CryptoInputParcel(signatureTime, getPassphrase(), isCachePassphrase(),
|
||||
getParcelableProxy(), getCryptoData());
|
||||
}
|
||||
|
||||
public Date getSignatureTime() {
|
||||
return mSignatureTime;
|
||||
@CheckResult
|
||||
public CryptoInputParcel withParcelableProxy(ParcelableProxy parcelableProxy) {
|
||||
return new AutoValue_CryptoInputParcel(getSignatureTime(), getPassphrase(), isCachePassphrase(),
|
||||
parcelableProxy, getCryptoData());
|
||||
}
|
||||
|
||||
public boolean hasPassphrase() {
|
||||
return mPassphrase != null;
|
||||
}
|
||||
|
||||
public Passphrase getPassphrase() {
|
||||
return mPassphrase;
|
||||
}
|
||||
|
||||
public static final Creator<CryptoInputParcel> CREATOR = new Creator<CryptoInputParcel>() {
|
||||
public CryptoInputParcel createFromParcel(final Parcel source) {
|
||||
return new CryptoInputParcel(source);
|
||||
}
|
||||
|
||||
public CryptoInputParcel[] newArray(final int size) {
|
||||
return new CryptoInputParcel[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("CryptoInput: { ");
|
||||
b.append(mSignatureTime).append(" ");
|
||||
if (mPassphrase != null) {
|
||||
b.append("passphrase");
|
||||
}
|
||||
if (mCryptoData != null) {
|
||||
b.append(mCryptoData.size());
|
||||
b.append(" hashes ");
|
||||
}
|
||||
b.append("}");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -523,7 +523,8 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
|
||||
|
||||
// if we don't want to execute the actual operation outside of this activity, drop out here
|
||||
if (!mExecuteBackupOperation) {
|
||||
((BackupActivity) getActivity()).handleBackupOperation(new CryptoInputParcel(passphrase));
|
||||
((BackupActivity) getActivity()).handleBackupOperation(
|
||||
CryptoInputParcel.createCryptoInputParcel(passphrase));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -531,7 +532,7 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
|
||||
mCachedBackupUri = TemporaryFileProvider.createFile(activity, filename,
|
||||
Constants.MIME_TYPE_ENCRYPTED_ALTERNATE);
|
||||
|
||||
cryptoOperation(new CryptoInputParcel(passphrase));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(passphrase));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -605,7 +606,8 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
|
||||
@Nullable
|
||||
@Override
|
||||
public BackupKeyringParcel createOperationInput() {
|
||||
return new BackupKeyringParcel(mMasterKeyIds, mExportSecret, true, true, mCachedBackupUri);
|
||||
return BackupKeyringParcel
|
||||
.createBackupKeyringParcel(mMasterKeyIds, mExportSecret, true, true, mCachedBackupUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -113,7 +113,7 @@ public class CertifyKeyFragment
|
||||
Notify.create(getActivity(), getString(R.string.select_key_to_certify),
|
||||
Notify.Style.ERROR).show();
|
||||
} else {
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -140,18 +140,17 @@ public class CertifyKeyFragment
|
||||
long selectedKeyId = mCertifyKeySpinner.getSelectedKeyId();
|
||||
|
||||
// fill values for this action
|
||||
CertifyActionsParcel actionsParcel = new CertifyActionsParcel(selectedKeyId);
|
||||
actionsParcel.mCertifyActions.addAll(certifyActions);
|
||||
CertifyActionsParcel.Builder actionsParcel = CertifyActionsParcel.builder(selectedKeyId);
|
||||
actionsParcel.addActions(certifyActions);
|
||||
|
||||
if (mUploadKeyCheckbox.isChecked()) {
|
||||
actionsParcel.keyServerUri = Preferences.getPreferences(getActivity())
|
||||
.getPreferredKeyserver();
|
||||
actionsParcel.setParcelableKeyServer(Preferences.getPreferences(getActivity()).getPreferredKeyserver());
|
||||
}
|
||||
|
||||
// cached for next cryptoOperation loop
|
||||
cacheActionsParcel(actionsParcel);
|
||||
|
||||
return actionsParcel;
|
||||
// cache for next cryptoOperation loop
|
||||
CertifyActionsParcel certifyActionsParcel = actionsParcel.build();
|
||||
cacheActionsParcel(certifyActionsParcel);
|
||||
return certifyActionsParcel;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -67,7 +67,7 @@ public class ConsolidateDialogActivity extends FragmentActivity
|
||||
|
||||
@Override
|
||||
public ConsolidateInputParcel createOperationInput() {
|
||||
return new ConsolidateInputParcel(mRecovery);
|
||||
return ConsolidateInputParcel.createConsolidateInputParcel(mRecovery);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
|
||||
import org.sufficientlysecure.keychain.service.UploadKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
|
||||
@@ -294,7 +295,7 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
}
|
||||
|
||||
private static SaveKeyringParcel createDefaultSaveKeyringParcel(CreateKeyActivity createKeyActivity) {
|
||||
SaveKeyringParcel saveKeyringParcel = new SaveKeyringParcel();
|
||||
SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
|
||||
|
||||
if (createKeyActivity.mCreateSecurityToken) {
|
||||
if (createKeyActivity.mSecurityTokenSign == null) {
|
||||
@@ -302,37 +303,40 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
createKeyActivity.mSecurityTokenDec = Constants.SECURITY_TOKEN_V2_DEC;
|
||||
createKeyActivity.mSecurityTokenAuth = Constants.SECURITY_TOKEN_V2_AUTH;
|
||||
}
|
||||
createKeyActivity.mSecurityTokenSign.addToSaveKeyringParcel(saveKeyringParcel, KeyFlags.SIGN_DATA | KeyFlags.CERTIFY_OTHER);
|
||||
createKeyActivity.mSecurityTokenDec.addToSaveKeyringParcel(saveKeyringParcel, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
|
||||
createKeyActivity.mSecurityTokenAuth.addToSaveKeyringParcel(saveKeyringParcel, KeyFlags.AUTHENTICATION);
|
||||
createKeyActivity.mSecurityTokenSign.addToSaveKeyringParcel(
|
||||
builder, KeyFlags.SIGN_DATA | KeyFlags.CERTIFY_OTHER);
|
||||
createKeyActivity.mSecurityTokenDec.addToSaveKeyringParcel(
|
||||
builder, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
|
||||
createKeyActivity.mSecurityTokenAuth.addToSaveKeyringParcel(builder, KeyFlags.AUTHENTICATION);
|
||||
|
||||
// use empty passphrase
|
||||
saveKeyringParcel.setNewUnlock(new ChangeUnlockParcel(new Passphrase()));
|
||||
builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase()));
|
||||
} else {
|
||||
Constants.addDefaultSubkeys(saveKeyringParcel);
|
||||
Constants.addDefaultSubkeys(builder);
|
||||
|
||||
if (createKeyActivity.mPassphrase != null) {
|
||||
saveKeyringParcel.setNewUnlock(new ChangeUnlockParcel(createKeyActivity.mPassphrase));
|
||||
builder.setNewUnlock(
|
||||
ChangeUnlockParcel.createUnLockParcelForNewKey(createKeyActivity.mPassphrase));
|
||||
} else {
|
||||
saveKeyringParcel.setNewUnlock(null);
|
||||
builder.setNewUnlock(null);
|
||||
}
|
||||
}
|
||||
String userId = KeyRing.createUserId(
|
||||
new OpenPgpUtils.UserId(createKeyActivity.mName, createKeyActivity.mEmail, null)
|
||||
);
|
||||
saveKeyringParcel.mAddUserIds.add(userId);
|
||||
saveKeyringParcel.mChangePrimaryUserId = userId;
|
||||
builder.addUserId(userId);
|
||||
builder.setChangePrimaryUserId(userId);
|
||||
if (createKeyActivity.mAdditionalEmails != null
|
||||
&& createKeyActivity.mAdditionalEmails.size() > 0) {
|
||||
for (String email : createKeyActivity.mAdditionalEmails) {
|
||||
String thisUserId = KeyRing.createUserId(
|
||||
new OpenPgpUtils.UserId(createKeyActivity.mName, email, null)
|
||||
);
|
||||
saveKeyringParcel.mAddUserIds.add(thisUserId);
|
||||
builder.addUserId(thisUserId);
|
||||
}
|
||||
}
|
||||
|
||||
return saveKeyringParcel;
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void checkEmailValidity() {
|
||||
@@ -425,11 +429,11 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
private void moveToCard(final EditKeyResult saveKeyResult) {
|
||||
CreateKeyActivity activity = (CreateKeyActivity) getActivity();
|
||||
|
||||
final SaveKeyringParcel changeKeyringParcel;
|
||||
SaveKeyringParcel.Builder builder;
|
||||
CachedPublicKeyRing key = (KeyRepository.createDatabaseInteractor(getContext()))
|
||||
.getCachedPublicKeyRing(saveKeyResult.mMasterKeyId);
|
||||
try {
|
||||
changeKeyringParcel = new SaveKeyringParcel(key.getMasterKeyId(), key.getFingerprint());
|
||||
builder = SaveKeyringParcel.buildChangeKeyringParcel(key.getMasterKeyId(), key.getFingerprint());
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
Log.e(Constants.TAG, "Key that should be moved to Security Token not found in database!");
|
||||
return;
|
||||
@@ -437,13 +441,13 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
|
||||
// define subkeys that should be moved to the card
|
||||
Cursor cursor = activity.getContentResolver().query(
|
||||
KeychainContract.Keys.buildKeysUri(changeKeyringParcel.mMasterKeyId),
|
||||
KeychainContract.Keys.buildKeysUri(builder.getMasterKeyId()),
|
||||
new String[]{KeychainContract.Keys.KEY_ID,}, null, null, null
|
||||
);
|
||||
try {
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
long subkeyId = cursor.getLong(0);
|
||||
changeKeyringParcel.getOrCreateSubkeyChange(subkeyId).mMoveKeyToSecurityToken = true;
|
||||
builder.addOrReplaceSubkeyChange(SubkeyChange.createMoveToSecurityTokenChange(subkeyId));
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
@@ -452,15 +456,17 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
}
|
||||
|
||||
// define new PIN and Admin PIN for the card
|
||||
changeKeyringParcel.mSecurityTokenPin = activity.mSecurityTokenPin;
|
||||
changeKeyringParcel.mSecurityTokenAdminPin = activity.mSecurityTokenAdminPin;
|
||||
builder.setSecurityTokenPin(activity.mSecurityTokenPin);
|
||||
builder.setSecurityTokenAdminPin(activity.mSecurityTokenAdminPin);
|
||||
|
||||
final SaveKeyringParcel saveKeyringParcel = builder.build();
|
||||
|
||||
CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult> callback
|
||||
= new CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult>() {
|
||||
|
||||
@Override
|
||||
public SaveKeyringParcel createOperationInput() {
|
||||
return changeKeyringParcel;
|
||||
return saveKeyringParcel;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -499,7 +505,7 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
|
||||
|
||||
mMoveToCardOpHelper = new CryptoOperationHelper<>(2, this, callback, R.string.progress_modify);
|
||||
mMoveToCardOpHelper.cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
mMoveToCardOpHelper.cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
}
|
||||
|
||||
private void uploadKey(final EditKeyResult saveKeyResult) {
|
||||
@@ -520,7 +526,7 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public UploadKeyringParcel createOperationInput() {
|
||||
return new UploadKeyringParcel(keyserver, masterKeyId);
|
||||
return UploadKeyringParcel.createWithKeyId(keyserver, masterKeyId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -235,7 +235,7 @@ public class CreateSecurityTokenImportResetFragment
|
||||
Intent intent = new Intent(getActivity(), SecurityTokenOperationActivity.class);
|
||||
RequiredInputParcel resetP = RequiredInputParcel.createSecurityTokenReset();
|
||||
intent.putExtra(SecurityTokenOperationActivity.EXTRA_REQUIRED_INPUT, resetP);
|
||||
intent.putExtra(SecurityTokenOperationActivity.EXTRA_CRYPTO_INPUT, new CryptoInputParcel());
|
||||
intent.putExtra(SecurityTokenOperationActivity.EXTRA_CRYPTO_INPUT, CryptoInputParcel.createCryptoInputParcel());
|
||||
startActivityForResult(intent, REQUEST_CODE_RESET);
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ public class CreateSecurityTokenImportResetFragment
|
||||
|
||||
@Override
|
||||
public ImportKeyringParcel createOperationInput() {
|
||||
return new ImportKeyringParcel(mKeyList, mKeyserver);
|
||||
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -159,7 +159,7 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
|
||||
|
||||
@Override
|
||||
public ImportKeyringParcel createOperationInput() {
|
||||
return new ImportKeyringParcel(keyList, keyserver);
|
||||
return ImportKeyringParcel.createImportKeyringParcel(keyList, keyserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -637,9 +637,9 @@ public class DecryptListFragment
|
||||
return null;
|
||||
}
|
||||
|
||||
PgpDecryptVerifyInputParcel decryptInput = new PgpDecryptVerifyInputParcel()
|
||||
PgpDecryptVerifyInputParcel.Builder decryptInput = PgpDecryptVerifyInputParcel.builder()
|
||||
.setAllowSymmetricDecryption(true);
|
||||
return new InputDataParcel(mCurrentInputUri, decryptInput);
|
||||
return InputDataParcel.createInputDataParcel(mCurrentInputUri, decryptInput.build());
|
||||
|
||||
}
|
||||
|
||||
@@ -779,7 +779,7 @@ public class DecryptListFragment
|
||||
|
||||
@Override
|
||||
public ImportKeyringParcel createOperationInput() {
|
||||
return new ImportKeyringParcel(keyList, keyserver);
|
||||
return ImportKeyringParcel.createImportKeyringParcel(keyList, keyserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -139,7 +139,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
|
||||
}
|
||||
|
||||
private void startRevocationOperation() {
|
||||
mRevokeOpHelper.cryptoOperation(new CryptoInputParcel(new Date(), false));
|
||||
mRevokeOpHelper.cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date(), false));
|
||||
}
|
||||
|
||||
private void startDeletionOperation() {
|
||||
@@ -151,7 +151,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
|
||||
return new CryptoOperationHelper.Callback<RevokeKeyringParcel, RevokeResult>() {
|
||||
@Override
|
||||
public RevokeKeyringParcel createOperationInput() {
|
||||
return new RevokeKeyringParcel(mMasterKeyIds[0], true,
|
||||
return RevokeKeyringParcel.createRevokeKeyringParcel(mMasterKeyIds[0], true,
|
||||
(ParcelableHkpKeyserver) getIntent().getParcelableExtra(EXTRA_KEYSERVER));
|
||||
}
|
||||
|
||||
@@ -183,9 +183,12 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
|
||||
return new CryptoOperationHelper.Callback<DeleteKeyringParcel, DeleteResult>() {
|
||||
@Override
|
||||
public DeleteKeyringParcel createOperationInput() {
|
||||
return new DeleteKeyringParcel(mMasterKeyIds, mHasSecret);
|
||||
if (mHasSecret) {
|
||||
return DeleteKeyringParcel.createDeleteSingleSecretKeyParcel(mMasterKeyIds[0]);
|
||||
} else {
|
||||
return DeleteKeyringParcel.createDeletePublicKeysParcel(mMasterKeyIds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCryptoOperationSuccess(DeleteResult result) {
|
||||
returnResult(result);
|
||||
|
||||
@@ -82,7 +82,7 @@ public class EditIdentitiesFragment extends Fragment
|
||||
|
||||
private Uri mDataUri;
|
||||
|
||||
private SaveKeyringParcel mSaveKeyringParcel;
|
||||
private SaveKeyringParcel.Builder mSkpBuilder;
|
||||
|
||||
private CryptoOperationHelper<SaveKeyringParcel, EditKeyResult> mEditOpHelper;
|
||||
private CryptoOperationHelper<UploadKeyringParcel, UploadResult> mUploadOpHelper;
|
||||
@@ -180,7 +180,7 @@ public class EditIdentitiesFragment extends Fragment
|
||||
return;
|
||||
}
|
||||
|
||||
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
|
||||
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
|
||||
mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback();
|
||||
|
||||
} catch (PgpKeyNotFoundException | NotFoundException e) {
|
||||
@@ -193,11 +193,11 @@ public class EditIdentitiesFragment extends Fragment
|
||||
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditIdentitiesFragment.this);
|
||||
|
||||
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
|
||||
mUserIdsAdapter.setEditMode(mSaveKeyringParcel);
|
||||
mUserIdsAdapter.setEditMode(mSkpBuilder);
|
||||
mUserIdsList.setAdapter(mUserIdsAdapter);
|
||||
|
||||
// TODO: SaveParcel from savedInstance?!
|
||||
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, false);
|
||||
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), false);
|
||||
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
|
||||
}
|
||||
|
||||
@@ -266,23 +266,23 @@ public class EditIdentitiesFragment extends Fragment
|
||||
switch (message.what) {
|
||||
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
|
||||
// toggle
|
||||
if (mSaveKeyringParcel.mChangePrimaryUserId != null
|
||||
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = null;
|
||||
if (mSkpBuilder.getChangePrimaryUserId() != null
|
||||
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
|
||||
mSkpBuilder.setChangePrimaryUserId(null);
|
||||
} else {
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = userId;
|
||||
mSkpBuilder.setChangePrimaryUserId(userId);
|
||||
}
|
||||
break;
|
||||
case EditUserIdDialogFragment.MESSAGE_REVOKE:
|
||||
// toggle
|
||||
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) {
|
||||
mSaveKeyringParcel.mRevokeUserIds.remove(userId);
|
||||
if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
|
||||
mSkpBuilder.removeRevokeUserId(userId);
|
||||
} else {
|
||||
mSaveKeyringParcel.mRevokeUserIds.add(userId);
|
||||
mSkpBuilder.addRevokeUserId(userId);
|
||||
// not possible to revoke and change to primary user id
|
||||
if (mSaveKeyringParcel.mChangePrimaryUserId != null
|
||||
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = null;
|
||||
if (mSkpBuilder.getChangePrimaryUserId() != null
|
||||
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
|
||||
mSkpBuilder.setChangePrimaryUserId(null);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -339,7 +339,7 @@ public class EditIdentitiesFragment extends Fragment
|
||||
= new CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult>() {
|
||||
@Override
|
||||
public SaveKeyringParcel createOperationInput() {
|
||||
return mSaveKeyringParcel;
|
||||
return mSkpBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -395,7 +395,7 @@ public class EditIdentitiesFragment extends Fragment
|
||||
|
||||
@Override
|
||||
public UploadKeyringParcel createOperationInput() {
|
||||
return new UploadKeyringParcel(keyserver, masterKeyId);
|
||||
return UploadKeyringParcel.createWithKeyId(keyserver, masterKeyId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -100,7 +100,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
|
||||
private Uri mDataUri;
|
||||
|
||||
private SaveKeyringParcel mSaveKeyringParcel;
|
||||
private SaveKeyringParcel.Builder mSkpBuilder;
|
||||
|
||||
private String mPrimaryUserId;
|
||||
|
||||
@@ -156,7 +156,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
if (mDataUri == null) {
|
||||
returnKeyringParcel();
|
||||
} else {
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
}
|
||||
}
|
||||
}, new OnClickListener() {
|
||||
@@ -184,13 +184,13 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
}
|
||||
|
||||
private void loadSaveKeyringParcel(SaveKeyringParcel saveKeyringParcel) {
|
||||
mSaveKeyringParcel = saveKeyringParcel;
|
||||
mPrimaryUserId = saveKeyringParcel.mChangePrimaryUserId;
|
||||
mSkpBuilder = SaveKeyringParcel.buildUpon(saveKeyringParcel);
|
||||
mPrimaryUserId = saveKeyringParcel.getChangePrimaryUserId();
|
||||
|
||||
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, true);
|
||||
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), true);
|
||||
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
|
||||
|
||||
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys, true);
|
||||
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSkpBuilder.getMutableAddSubKeys(), true);
|
||||
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
return;
|
||||
}
|
||||
|
||||
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
|
||||
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
|
||||
mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback();
|
||||
|
||||
} catch (PgpKeyNotFoundException | NotFoundException e) {
|
||||
@@ -227,18 +227,18 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this);
|
||||
|
||||
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
|
||||
mUserIdsAdapter.setEditMode(mSaveKeyringParcel);
|
||||
mUserIdsAdapter.setEditMode(mSkpBuilder);
|
||||
mUserIdsList.setAdapter(mUserIdsAdapter);
|
||||
|
||||
// TODO: SaveParcel from savedInstance?!
|
||||
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, false);
|
||||
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), false);
|
||||
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
|
||||
|
||||
mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0);
|
||||
mSubkeysAdapter.setEditMode(mSaveKeyringParcel);
|
||||
mSubkeysAdapter.setEditMode(mSkpBuilder);
|
||||
mSubkeysList.setAdapter(mSubkeysAdapter);
|
||||
|
||||
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys, false);
|
||||
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSkpBuilder.getMutableAddSubKeys(), false);
|
||||
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
|
||||
}
|
||||
|
||||
@@ -341,7 +341,8 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
Bundle data = message.getData();
|
||||
|
||||
// cache new returned passphrase!
|
||||
mSaveKeyringParcel.setNewUnlock(new ChangeUnlockParcel(
|
||||
mSkpBuilder.setNewUnlock(ChangeUnlockParcel.createChangeUnlockParcel(
|
||||
mSkpBuilder.getMasterKeyId(), mSkpBuilder.getFingerprint(),
|
||||
(Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE)));
|
||||
}
|
||||
}
|
||||
@@ -367,23 +368,23 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
switch (message.what) {
|
||||
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
|
||||
// toggle
|
||||
if (mSaveKeyringParcel.mChangePrimaryUserId != null
|
||||
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = null;
|
||||
String changePrimaryUserId = mSkpBuilder.getChangePrimaryUserId();
|
||||
if (changePrimaryUserId != null && changePrimaryUserId.equals(userId)) {
|
||||
mSkpBuilder.setChangePrimaryUserId(null);
|
||||
} else {
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = userId;
|
||||
mSkpBuilder.setChangePrimaryUserId(userId);
|
||||
}
|
||||
break;
|
||||
case EditUserIdDialogFragment.MESSAGE_REVOKE:
|
||||
// toggle
|
||||
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) {
|
||||
mSaveKeyringParcel.mRevokeUserIds.remove(userId);
|
||||
if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
|
||||
mSkpBuilder.removeRevokeUserId(userId);
|
||||
} else {
|
||||
mSaveKeyringParcel.mRevokeUserIds.add(userId);
|
||||
mSkpBuilder.addRevokeUserId(userId);
|
||||
// not possible to revoke and change to primary user id
|
||||
if (mSaveKeyringParcel.mChangePrimaryUserId != null
|
||||
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = null;
|
||||
if (mSkpBuilder.getChangePrimaryUserId() != null
|
||||
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
|
||||
mSkpBuilder.setChangePrimaryUserId(null);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -416,10 +417,10 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
break;
|
||||
case EditSubkeyDialogFragment.MESSAGE_REVOKE:
|
||||
// toggle
|
||||
if (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId)) {
|
||||
mSaveKeyringParcel.mRevokeSubKeys.remove(keyId);
|
||||
if (mSkpBuilder.getMutableRevokeSubKeys().contains(keyId)) {
|
||||
mSkpBuilder.removeRevokeSubkey(keyId);
|
||||
} else {
|
||||
mSaveKeyringParcel.mRevokeSubKeys.add(keyId);
|
||||
mSkpBuilder.addRevokeSubkey(keyId);
|
||||
}
|
||||
break;
|
||||
case EditSubkeyDialogFragment.MESSAGE_STRIP: {
|
||||
@@ -429,16 +430,11 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
break;
|
||||
}
|
||||
|
||||
SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId);
|
||||
if (change == null) {
|
||||
mSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false));
|
||||
break;
|
||||
}
|
||||
// toggle
|
||||
change.mDummyStrip = !change.mDummyStrip;
|
||||
if (change.mDummyStrip && change.mMoveKeyToSecurityToken) {
|
||||
// User had chosen to divert key, but now wants to strip it instead.
|
||||
change.mMoveKeyToSecurityToken = false;
|
||||
SubkeyChange change = mSkpBuilder.getSubkeyChange(keyId);
|
||||
if (change == null || !change.getDummyStrip()) {
|
||||
mSkpBuilder.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId));
|
||||
} else {
|
||||
mSkpBuilder.removeSubkeyChange(change);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -478,19 +474,13 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
break;
|
||||
}
|
||||
|
||||
SubkeyChange change;
|
||||
change = mSaveKeyringParcel.getSubkeyChange(keyId);
|
||||
if (change == null) {
|
||||
mSaveKeyringParcel.mChangeSubKeys.add(
|
||||
new SubkeyChange(keyId, false, true)
|
||||
);
|
||||
SubkeyChange change = mSkpBuilder.getSubkeyChange(keyId);
|
||||
if (change == null || !change.getMoveKeyToSecurityToken()) {
|
||||
mSkpBuilder.addOrReplaceSubkeyChange(
|
||||
SubkeyChange.createMoveToSecurityTokenChange(keyId));
|
||||
break;
|
||||
}
|
||||
// toggle
|
||||
change.mMoveKeyToSecurityToken = !change.mMoveKeyToSecurityToken;
|
||||
if (change.mMoveKeyToSecurityToken && change.mDummyStrip) {
|
||||
// User had chosen to strip key, but now wants to divert it.
|
||||
change.mDummyStrip = false;
|
||||
} else {
|
||||
mSkpBuilder.removeSubkeyChange(change);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -522,9 +512,10 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY:
|
||||
mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry =
|
||||
(Long) message.getData().getSerializable(
|
||||
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
|
||||
Long expiry = (Long) message.getData().getSerializable(
|
||||
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
|
||||
mSkpBuilder.addOrReplaceSubkeyChange(
|
||||
SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry));
|
||||
break;
|
||||
}
|
||||
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
|
||||
@@ -585,20 +576,20 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
}
|
||||
|
||||
protected void returnKeyringParcel() {
|
||||
if (mSaveKeyringParcel.mAddUserIds.size() == 0) {
|
||||
if (mSkpBuilder.getMutableAddUserIds().size() == 0) {
|
||||
Notify.create(getActivity(), R.string.edit_key_error_add_identity, Notify.Style.ERROR).show();
|
||||
return;
|
||||
}
|
||||
if (mSaveKeyringParcel.mAddSubKeys.size() == 0) {
|
||||
if (mSkpBuilder.getMutableAddSubKeys().size() == 0) {
|
||||
Notify.create(getActivity(), R.string.edit_key_error_add_subkey, Notify.Style.ERROR).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// use first user id as primary
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = mSaveKeyringParcel.mAddUserIds.get(0);
|
||||
String firstUserId = mSkpBuilder.getMutableAddUserIds().get(0);
|
||||
mSkpBuilder.setChangePrimaryUserId(firstUserId);
|
||||
|
||||
Intent returnIntent = new Intent();
|
||||
returnIntent.putExtra(EditKeyActivity.EXTRA_SAVE_KEYRING_PARCEL, mSaveKeyringParcel);
|
||||
returnIntent.putExtra(EditKeyActivity.EXTRA_SAVE_KEYRING_PARCEL, mSkpBuilder.build());
|
||||
getActivity().setResult(Activity.RESULT_OK, returnIntent);
|
||||
getActivity().finish();
|
||||
}
|
||||
@@ -619,7 +610,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
|
||||
|
||||
@Override
|
||||
public SaveKeyringParcel createOperationInput() {
|
||||
return mSaveKeyringParcel;
|
||||
return mSkpBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -345,19 +345,19 @@ public class EncryptFilesFragment
|
||||
case R.id.encrypt_save: {
|
||||
hideKeyboard();
|
||||
mAfterEncryptAction = AfterEncryptAction.SAVE;
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
break;
|
||||
}
|
||||
case R.id.encrypt_share: {
|
||||
hideKeyboard();
|
||||
mAfterEncryptAction = AfterEncryptAction.SHARE;
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
break;
|
||||
}
|
||||
case R.id.encrypt_copy: {
|
||||
hideKeyboard();
|
||||
mAfterEncryptAction = AfterEncryptAction.COPY;
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
break;
|
||||
}
|
||||
case R.id.check_use_armor: {
|
||||
@@ -577,12 +577,10 @@ public class EncryptFilesFragment
|
||||
}
|
||||
|
||||
public SignEncryptParcel createOperationInput() {
|
||||
|
||||
SignEncryptParcel actionsParcel = getCachedActionsParcel();
|
||||
|
||||
// we have three cases here: nothing cached, cached except output, fully cached
|
||||
if (actionsParcel == null) {
|
||||
|
||||
// clear output uris for now, they will be created by prepareOutputStreams later
|
||||
mOutputUris = null;
|
||||
|
||||
@@ -593,7 +591,6 @@ public class EncryptFilesFragment
|
||||
}
|
||||
|
||||
cacheActionsParcel(actionsParcel);
|
||||
|
||||
}
|
||||
|
||||
// if it's incomplete, prepare output streams
|
||||
@@ -606,9 +603,10 @@ public class EncryptFilesFragment
|
||||
}
|
||||
}
|
||||
|
||||
actionsParcel.addOutputUris(mOutputUris);
|
||||
actionsParcel = SignEncryptParcel.builder(actionsParcel)
|
||||
.addOutputUris(mOutputUris)
|
||||
.build();
|
||||
cacheActionsParcel(actionsParcel);
|
||||
|
||||
}
|
||||
|
||||
return actionsParcel;
|
||||
@@ -623,21 +621,13 @@ public class EncryptFilesFragment
|
||||
}
|
||||
|
||||
// fill values for this action
|
||||
PgpSignEncryptData data = new PgpSignEncryptData();
|
||||
PgpSignEncryptData.Builder data = PgpSignEncryptData.builder();
|
||||
|
||||
if (mUseCompression) {
|
||||
data.setCompressionAlgorithm(
|
||||
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
|
||||
} else {
|
||||
data.setCompressionAlgorithm(
|
||||
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
|
||||
if (!mUseCompression) {
|
||||
data.setCompressionAlgorithm(PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
|
||||
}
|
||||
data.setHiddenRecipients(mHiddenRecipients);
|
||||
data.setEnableAsciiArmorOutput(mAfterEncryptAction == AfterEncryptAction.COPY || mUseArmor);
|
||||
data.setSymmetricEncryptionAlgorithm(
|
||||
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
|
||||
data.setSignatureHashAlgorithm(
|
||||
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
|
||||
|
||||
EncryptActivity encryptActivity = (EncryptActivity) getActivity();
|
||||
EncryptModeFragment modeFragment = encryptActivity.getModeFragment();
|
||||
@@ -675,10 +665,9 @@ public class EncryptFilesFragment
|
||||
}
|
||||
|
||||
|
||||
SignEncryptParcel parcel = new SignEncryptParcel(data);
|
||||
parcel.addInputUris(mFilesAdapter.getAsArrayList());
|
||||
|
||||
return parcel;
|
||||
SignEncryptParcel.Builder builder = SignEncryptParcel.builder(data.build());
|
||||
builder.addInputUris(mFilesAdapter.getAsArrayList());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private Intent createSendIntent() {
|
||||
@@ -733,7 +722,7 @@ public class EncryptFilesFragment
|
||||
mOutputUris.add(data.getData());
|
||||
// make sure this is correct at this point
|
||||
mAfterEncryptAction = AfterEncryptAction.SAVE;
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
} else if (resultCode == Activity.RESULT_CANCELED) {
|
||||
onCryptoOperationCancelled();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
@@ -38,7 +43,7 @@ import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
|
||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
|
||||
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
@@ -49,10 +54,6 @@ import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class EncryptTextFragment
|
||||
extends CachingCryptoOperationFragment<SignEncryptParcel, SignEncryptResult> {
|
||||
|
||||
@@ -181,18 +182,18 @@ public class EncryptTextFragment
|
||||
case R.id.encrypt_copy: {
|
||||
hideKeyboard();
|
||||
mShareAfterEncrypt = false;
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
break;
|
||||
}
|
||||
case R.id.encrypt_share: {
|
||||
hideKeyboard();
|
||||
mShareAfterEncrypt = true;
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
break;
|
||||
}
|
||||
case R.id.encrypt_paste: {
|
||||
hideKeyboard();
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -233,22 +234,14 @@ public class EncryptTextFragment
|
||||
}
|
||||
|
||||
// fill values for this action
|
||||
PgpSignEncryptData data = new PgpSignEncryptData();
|
||||
PgpSignEncryptData.Builder data = PgpSignEncryptData.builder();
|
||||
|
||||
data.setCleartextSignature(true);
|
||||
|
||||
if (mUseCompression) {
|
||||
data.setCompressionAlgorithm(
|
||||
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
|
||||
} else {
|
||||
data.setCompressionAlgorithm(
|
||||
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
|
||||
if (!mUseCompression) {
|
||||
data.setCompressionAlgorithm(OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
|
||||
}
|
||||
data.setHiddenRecipients(mHiddenRecipients);
|
||||
data.setSymmetricEncryptionAlgorithm(
|
||||
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
|
||||
data.setSignatureHashAlgorithm(
|
||||
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
|
||||
|
||||
// Always use armor for messages
|
||||
data.setEnableAsciiArmorOutput(true);
|
||||
@@ -286,10 +279,7 @@ public class EncryptTextFragment
|
||||
data.setSymmetricPassphrase(passphrase);
|
||||
}
|
||||
|
||||
SignEncryptParcel parcel = new SignEncryptParcel(data);
|
||||
parcel.setBytes(mMessage.getBytes());
|
||||
|
||||
return parcel;
|
||||
return SignEncryptParcel.createSignEncryptParcel(data.build(), mMessage.getBytes());
|
||||
}
|
||||
|
||||
private void copyToClipboard(SignEncryptResult result) {
|
||||
|
||||
@@ -357,7 +357,7 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen
|
||||
return;
|
||||
}
|
||||
|
||||
ImportKeyringParcel inputParcel = new ImportKeyringParcel(null, null);
|
||||
ImportKeyringParcel inputParcel = ImportKeyringParcel.createImportKeyringParcel(null, null);
|
||||
ImportKeysOperationCallback callback = new ImportKeysOperationCallback(this, inputParcel, null);
|
||||
mOpHelper = new CryptoOperationHelper<>(1, this, callback, R.string.progress_importing);
|
||||
mOpHelper.cryptoOperation();
|
||||
|
||||
@@ -223,7 +223,7 @@ public class ImportKeysProxyActivity extends FragmentActivity
|
||||
|
||||
@Override
|
||||
public ImportKeyringParcel createOperationInput() {
|
||||
return new ImportKeyringParcel(mKeyList, mKeyserver);
|
||||
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -519,7 +519,7 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
||||
|
||||
@Override
|
||||
public ImportKeyringParcel createOperationInput() {
|
||||
return new ImportKeyringParcel(mKeyList, mKeyserver);
|
||||
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -553,7 +553,7 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
||||
|
||||
@Override
|
||||
public ConsolidateInputParcel createOperationInput() {
|
||||
return new ConsolidateInputParcel(false); // we want to perform a full consolidate
|
||||
return ConsolidateInputParcel.createConsolidateInputParcel(false); // we want to perform a full consolidate
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -586,7 +586,7 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
||||
|
||||
@Override
|
||||
public BenchmarkInputParcel createOperationInput() {
|
||||
return new BenchmarkInputParcel(); // we want to perform a full consolidate
|
||||
return BenchmarkInputParcel.newInstance(); // we want to perform a full consolidate
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,7 +70,7 @@ public class OrbotRequiredDialogActivity extends FragmentActivity
|
||||
mCryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT);
|
||||
if (mCryptoInputParcel == null) {
|
||||
// compatibility with usages that don't use a CryptoInputParcel
|
||||
mCryptoInputParcel = new CryptoInputParcel();
|
||||
mCryptoInputParcel = CryptoInputParcel.createCryptoInputParcel();
|
||||
}
|
||||
|
||||
mMessenger = getIntent().getParcelableExtra(EXTRA_MESSENGER);
|
||||
@@ -147,7 +147,7 @@ public class OrbotRequiredDialogActivity extends FragmentActivity
|
||||
public void onNeutralButton() {
|
||||
sendMessage(MESSAGE_ORBOT_IGNORE);
|
||||
Intent intent = new Intent();
|
||||
mCryptoInputParcel.addParcelableProxy(ParcelableProxy.getForNoProxy());
|
||||
mCryptoInputParcel = mCryptoInputParcel.withParcelableProxy(ParcelableProxy.getForNoProxy());
|
||||
intent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel);
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
|
||||
@@ -99,7 +99,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
|
||||
CryptoInputParcel cryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT);
|
||||
if (cryptoInputParcel == null) {
|
||||
cryptoInputParcel = new CryptoInputParcel();
|
||||
cryptoInputParcel = CryptoInputParcel.createCryptoInputParcel();
|
||||
getIntent().putExtra(EXTRA_CRYPTO_INPUT, cryptoInputParcel);
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
if (pubRing.getSecretKeyType(requiredInput.getSubKeyId()) == SecretKeyType.PASSPHRASE_EMPTY) {
|
||||
// also return passphrase back to activity
|
||||
Intent returnIntent = new Intent();
|
||||
cryptoInputParcel.mPassphrase = new Passphrase("");
|
||||
cryptoInputParcel = cryptoInputParcel.withPassphrase(new Passphrase(""));
|
||||
returnIntent.putExtra(RESULT_CRYPTO_INPUT, cryptoInputParcel);
|
||||
setResult(RESULT_OK, returnIntent);
|
||||
finish();
|
||||
@@ -539,7 +539,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
|
||||
CryptoInputParcel inputParcel = getArguments().getParcelable(EXTRA_CRYPTO_INPUT);
|
||||
// noinspection ConstantConditions, we handle the non-null case in PassphraseDialogActivity.onCreate()
|
||||
inputParcel.mPassphrase = passphrase;
|
||||
inputParcel = inputParcel.withPassphrase(passphrase);
|
||||
|
||||
((PassphraseDialogActivity) getActivity()).handleResult(inputParcel);
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ public class SafeSlingerActivity extends BaseActivity
|
||||
|
||||
@Override
|
||||
public ImportKeyringParcel createOperationInput() {
|
||||
return new ImportKeyringParcel(mKeyList, mKeyserver);
|
||||
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -206,7 +206,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
||||
for (int i = 0; i < mRequiredInput.mInputData.length; i++) {
|
||||
byte[] encryptedSessionKey = mRequiredInput.mInputData[i];
|
||||
byte[] decryptedSessionKey = mSecurityTokenHelper.decryptSessionKey(encryptedSessionKey, publicKeyRing.getPublicKey(tokenKeyId));
|
||||
mInputParcel.addCryptoData(encryptedSessionKey, decryptedSessionKey);
|
||||
mInputParcel = mInputParcel.withCryptoData(encryptedSessionKey, decryptedSessionKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -218,13 +218,13 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
||||
throw new IOException(getString(R.string.error_wrong_security_token));
|
||||
}
|
||||
|
||||
mInputParcel.addSignatureTime(mRequiredInput.mSignatureTime);
|
||||
mInputParcel = mInputParcel.withSignatureTime(mRequiredInput.mSignatureTime);
|
||||
|
||||
for (int i = 0; i < mRequiredInput.mInputData.length; i++) {
|
||||
byte[] hash = mRequiredInput.mInputData[i];
|
||||
int algo = mRequiredInput.mSignAlgos[i];
|
||||
byte[] signedHash = mSecurityTokenHelper.calculateSignature(hash, algo);
|
||||
mInputParcel.addCryptoData(hash, signedHash);
|
||||
mInputParcel = mInputParcel.withCryptoData(hash, signedHash);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -266,7 +266,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
|
||||
mSecurityTokenHelper.changeKey(key, passphrase);
|
||||
|
||||
// TODO: Is this really used anywhere?
|
||||
mInputParcel.addCryptoData(subkeyBytes, tokenSerialNumber);
|
||||
mInputParcel = mInputParcel.withCryptoData(subkeyBytes, tokenSerialNumber);
|
||||
}
|
||||
|
||||
// change PINs afterwards
|
||||
|
||||
@@ -144,7 +144,7 @@ public class UploadKeyActivity extends BaseActivity
|
||||
public UploadKeyringParcel createOperationInput() {
|
||||
long[] masterKeyIds = getIntent().getLongArrayExtra(MultiUserIdsFragment.EXTRA_KEY_IDS);
|
||||
|
||||
return new UploadKeyringParcel(mKeyserver, masterKeyIds[0]);
|
||||
return UploadKeyringParcel.createWithKeyId(mKeyserver, masterKeyIds[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -82,7 +82,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
|
||||
private long mMasterKeyId;
|
||||
private byte[] mFingerprint;
|
||||
private boolean mHasSecret;
|
||||
private SaveKeyringParcel mEditModeSaveKeyringParcel;
|
||||
private SaveKeyringParcel.Builder mEditModeSkpBuilder;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
|
||||
@@ -250,15 +250,15 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
|
||||
mEditModeSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint);
|
||||
mEditModeSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
|
||||
|
||||
mSubkeysAddedAdapter =
|
||||
new SubkeysAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddSubKeys, false);
|
||||
mSubkeysAddedAdapter = new SubkeysAddedAdapter(
|
||||
getActivity(), mEditModeSkpBuilder.getMutableAddSubKeys(), false);
|
||||
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
|
||||
mSubkeysAddedLayout.setVisibility(View.VISIBLE);
|
||||
mSubkeyAddFabLayout.setDisplayedChild(1);
|
||||
|
||||
mSubkeysAdapter.setEditMode(mEditModeSaveKeyringParcel);
|
||||
mSubkeysAdapter.setEditMode(mEditModeSkpBuilder);
|
||||
getLoaderManager().restartLoader(LOADER_ID_SUBKEYS, null, ViewKeyAdvSubkeysFragment.this);
|
||||
|
||||
mode.setTitle(R.string.title_edit_subkeys);
|
||||
@@ -280,7 +280,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
mEditModeSaveKeyringParcel = null;
|
||||
mEditModeSkpBuilder = null;
|
||||
mSubkeysAdapter.setEditMode(null);
|
||||
mSubkeysAddedLayout.setVisibility(View.GONE);
|
||||
mSubkeyAddFabLayout.setDisplayedChild(0);
|
||||
@@ -323,10 +323,10 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
|
||||
break;
|
||||
case EditSubkeyDialogFragment.MESSAGE_REVOKE:
|
||||
// toggle
|
||||
if (mEditModeSaveKeyringParcel.mRevokeSubKeys.contains(keyId)) {
|
||||
mEditModeSaveKeyringParcel.mRevokeSubKeys.remove(keyId);
|
||||
if (mEditModeSkpBuilder.getMutableRevokeSubKeys().contains(keyId)) {
|
||||
mEditModeSkpBuilder.removeRevokeSubkey(keyId);
|
||||
} else {
|
||||
mEditModeSaveKeyringParcel.mRevokeSubKeys.add(keyId);
|
||||
mEditModeSkpBuilder.addRevokeSubkey(keyId);
|
||||
}
|
||||
break;
|
||||
case EditSubkeyDialogFragment.MESSAGE_STRIP: {
|
||||
@@ -336,16 +336,11 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
|
||||
break;
|
||||
}
|
||||
|
||||
SubkeyChange change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId);
|
||||
if (change == null) {
|
||||
mEditModeSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false));
|
||||
break;
|
||||
}
|
||||
// toggle
|
||||
change.mDummyStrip = !change.mDummyStrip;
|
||||
if (change.mDummyStrip && change.mMoveKeyToSecurityToken) {
|
||||
// User had chosen to divert key, but now wants to strip it instead.
|
||||
change.mMoveKeyToSecurityToken = false;
|
||||
SubkeyChange change = mEditModeSkpBuilder.getSubkeyChange(keyId);
|
||||
if (change == null || !change.getDummyStrip()) {
|
||||
mEditModeSkpBuilder.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId));
|
||||
} else {
|
||||
mEditModeSkpBuilder.removeSubkeyChange(change);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -385,19 +380,12 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
|
||||
break;
|
||||
}
|
||||
|
||||
SubkeyChange change;
|
||||
change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId);
|
||||
if (change == null) {
|
||||
mEditModeSaveKeyringParcel.mChangeSubKeys.add(
|
||||
new SubkeyChange(keyId, false, true)
|
||||
);
|
||||
break;
|
||||
}
|
||||
// toggle
|
||||
change.mMoveKeyToSecurityToken = !change.mMoveKeyToSecurityToken;
|
||||
if (change.mMoveKeyToSecurityToken && change.mDummyStrip) {
|
||||
// User had chosen to strip key, but now wants to divert it.
|
||||
change.mDummyStrip = false;
|
||||
SubkeyChange change = mEditModeSkpBuilder.getSubkeyChange(keyId);
|
||||
if (change == null || !change.getMoveKeyToSecurityToken()) {
|
||||
mEditModeSkpBuilder.addOrReplaceSubkeyChange(
|
||||
SubkeyChange.createMoveToSecurityTokenChange(keyId));
|
||||
} else {
|
||||
mEditModeSkpBuilder.removeSubkeyChange(change);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -429,9 +417,10 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY:
|
||||
mEditModeSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry =
|
||||
(Long) message.getData().getSerializable(
|
||||
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
|
||||
Long expiry = (Long) message.getData().getSerializable(
|
||||
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
|
||||
mEditModeSkpBuilder.addOrReplaceSubkeyChange(
|
||||
SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry));
|
||||
break;
|
||||
}
|
||||
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
|
||||
@@ -458,7 +447,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
|
||||
|
||||
@Override
|
||||
public SaveKeyringParcel createOperationInput() {
|
||||
return mEditModeSaveKeyringParcel;
|
||||
return mEditModeSkpBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -79,7 +79,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
||||
private long mMasterKeyId;
|
||||
private byte[] mFingerprint;
|
||||
private boolean mHasSecret;
|
||||
private SaveKeyringParcel mEditModeSaveKeyringParcel;
|
||||
private SaveKeyringParcel.Builder mSkpBuilder;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
|
||||
@@ -122,7 +122,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
||||
}
|
||||
|
||||
private void showOrEditUserIdInfo(final int position) {
|
||||
if (mEditModeSaveKeyringParcel != null) {
|
||||
if (mSkpBuilder != null) {
|
||||
editUserId(position);
|
||||
} else {
|
||||
showUserIdInfo(position);
|
||||
@@ -140,23 +140,23 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
||||
switch (message.what) {
|
||||
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
|
||||
// toggle
|
||||
if (mEditModeSaveKeyringParcel.mChangePrimaryUserId != null
|
||||
&& mEditModeSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
|
||||
mEditModeSaveKeyringParcel.mChangePrimaryUserId = null;
|
||||
if (mSkpBuilder.getChangePrimaryUserId() != null
|
||||
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
|
||||
mSkpBuilder.setChangePrimaryUserId(null);
|
||||
} else {
|
||||
mEditModeSaveKeyringParcel.mChangePrimaryUserId = userId;
|
||||
mSkpBuilder.setChangePrimaryUserId(userId);
|
||||
}
|
||||
break;
|
||||
case EditUserIdDialogFragment.MESSAGE_REVOKE:
|
||||
// toggle
|
||||
if (mEditModeSaveKeyringParcel.mRevokeUserIds.contains(userId)) {
|
||||
mEditModeSaveKeyringParcel.mRevokeUserIds.remove(userId);
|
||||
if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
|
||||
mSkpBuilder.removeRevokeUserId(userId);
|
||||
} else {
|
||||
mEditModeSaveKeyringParcel.mRevokeUserIds.add(userId);
|
||||
mSkpBuilder.addRevokeUserId(userId);
|
||||
// not possible to revoke and change to primary user id
|
||||
if (mEditModeSaveKeyringParcel.mChangePrimaryUserId != null
|
||||
&& mEditModeSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
|
||||
mEditModeSaveKeyringParcel.mChangePrimaryUserId = null;
|
||||
if (mSkpBuilder.getChangePrimaryUserId() != null
|
||||
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
|
||||
mSkpBuilder.setChangePrimaryUserId(null);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -342,15 +342,15 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
|
||||
mEditModeSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint);
|
||||
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
|
||||
|
||||
mUserIdsAddedAdapter =
|
||||
new UserIdsAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddUserIds, false);
|
||||
new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), false);
|
||||
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
|
||||
mUserIdsAddedLayout.setVisibility(View.VISIBLE);
|
||||
mUserIdAddFabLayout.setDisplayedChild(1);
|
||||
|
||||
mUserIdsAdapter.setEditMode(mEditModeSaveKeyringParcel);
|
||||
mUserIdsAdapter.setEditMode(mSkpBuilder);
|
||||
getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this);
|
||||
|
||||
mode.setTitle(R.string.title_edit_identities);
|
||||
@@ -372,7 +372,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
mEditModeSaveKeyringParcel = null;
|
||||
mSkpBuilder = null;
|
||||
mUserIdsAdapter.setEditMode(null);
|
||||
mUserIdsAddedLayout.setVisibility(View.GONE);
|
||||
mUserIdAddFabLayout.setDisplayedChild(0);
|
||||
@@ -387,7 +387,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
||||
|
||||
@Override
|
||||
public SaveKeyringParcel createOperationInput() {
|
||||
return mEditModeSaveKeyringParcel;
|
||||
return mSkpBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -213,7 +213,7 @@ public class ViewKeySecurityTokenFragment
|
||||
|
||||
@Override
|
||||
public PromoteKeyringParcel createOperationInput() {
|
||||
return new PromoteKeyringParcel(mMasterKeyId, mCardAid, mSubKeyIds);
|
||||
return PromoteKeyringParcel.createPromoteKeyringParcel(mMasterKeyId, mCardAid, mSubKeyIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -237,7 +237,11 @@ public class ImportKeysAdapter extends RecyclerView.Adapter<ImportKeysAdapter.Vi
|
||||
keyserver = entry.getKeyserver();
|
||||
}
|
||||
|
||||
return new ImportKeyringParcel(keysList, keyserver, skipSave);
|
||||
if (skipSave) {
|
||||
return ImportKeyringParcel.createWithSkipSave(keysList, keyserver);
|
||||
} else {
|
||||
return ImportKeyringParcel.createImportKeyringParcel(keysList, keyserver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.os.Parcel;
|
||||
@@ -35,8 +38,6 @@ import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class MultiUserIdsAdapter extends CursorAdapter {
|
||||
private LayoutInflater mInflater;
|
||||
private final ArrayList<Boolean> mCheckStates;
|
||||
@@ -178,11 +179,12 @@ public class MultiUserIdsAdapter extends CursorAdapter {
|
||||
p.recycle();
|
||||
|
||||
CertifyAction action = actions.get(keyId);
|
||||
if (actions.get(keyId) == null) {
|
||||
actions.put(keyId, new CertifyAction(keyId, uids, null));
|
||||
if (action == null) {
|
||||
action = CertifyAction.createForUserIds(keyId, uids);
|
||||
} else {
|
||||
action.mUserIds.addAll(uids);
|
||||
action = action.withAddedUserIds(uids);
|
||||
}
|
||||
actions.put(keyId, action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.adapter;
|
||||
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.database.Cursor;
|
||||
@@ -42,13 +47,9 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class SubkeysAdapter extends CursorAdapter {
|
||||
private LayoutInflater mInflater;
|
||||
private SaveKeyringParcel mSaveKeyringParcel;
|
||||
private SaveKeyringParcel.Builder mSkpBuilder;
|
||||
|
||||
private boolean mHasAnySecret;
|
||||
private ColorStateList mDefaultTextColor;
|
||||
@@ -177,12 +178,9 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
cursor.getString(INDEX_KEY_CURVE_OID)
|
||||
));
|
||||
|
||||
SubkeyChange change = mSaveKeyringParcel != null
|
||||
? mSaveKeyringParcel.getSubkeyChange(keyId)
|
||||
: null;
|
||||
|
||||
if (change != null && (change.mDummyStrip || change.mMoveKeyToSecurityToken)) {
|
||||
if (change.mDummyStrip) {
|
||||
SubkeyChange change = mSkpBuilder != null ? mSkpBuilder.getSubkeyChange(keyId) : null;
|
||||
if (change != null && (change.getDummyStrip() || change.getMoveKeyToSecurityToken())) {
|
||||
if (change.getDummyStrip()) {
|
||||
algorithmStr.append(", ");
|
||||
final SpannableString boldStripped = new SpannableString(
|
||||
context.getString(R.string.key_stripped)
|
||||
@@ -190,7 +188,7 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
boldStripped.setSpan(new StyleSpan(Typeface.BOLD), 0, boldStripped.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
algorithmStr.append(boldStripped);
|
||||
}
|
||||
if (change.mMoveKeyToSecurityToken) {
|
||||
if (change.getMoveKeyToSecurityToken()) {
|
||||
algorithmStr.append(", ");
|
||||
final SpannableString boldDivert = new SpannableString(
|
||||
context.getString(R.string.key_divert)
|
||||
@@ -242,8 +240,8 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
}
|
||||
|
||||
// for edit key
|
||||
if (mSaveKeyringParcel != null) {
|
||||
boolean revokeThisSubkey = (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId));
|
||||
if (mSkpBuilder != null) {
|
||||
boolean revokeThisSubkey = (mSkpBuilder.getMutableRevokeSubKeys().contains(keyId));
|
||||
|
||||
if (revokeThisSubkey) {
|
||||
if (!isRevoked) {
|
||||
@@ -251,12 +249,12 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
SaveKeyringParcel.SubkeyChange subkeyChange = mSaveKeyringParcel.getSubkeyChange(keyId);
|
||||
SaveKeyringParcel.SubkeyChange subkeyChange = mSkpBuilder.getSubkeyChange(keyId);
|
||||
if (subkeyChange != null) {
|
||||
if (subkeyChange.mExpiry == null || subkeyChange.mExpiry == 0L) {
|
||||
if (subkeyChange.getExpiry() == null || subkeyChange.getExpiry() == 0L) {
|
||||
expiryDate = null;
|
||||
} else {
|
||||
expiryDate = new Date(subkeyChange.mExpiry * 1000);
|
||||
expiryDate = new Date(subkeyChange.getExpiry() * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,7 +343,7 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
// Disable selection of items, http://stackoverflow.com/a/4075045
|
||||
@Override
|
||||
public boolean areAllItemsEnabled() {
|
||||
if (mSaveKeyringParcel == null) {
|
||||
if (mSkpBuilder == null) {
|
||||
return false;
|
||||
} else {
|
||||
return super.areAllItemsEnabled();
|
||||
@@ -355,7 +353,7 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
// Disable selection of items, http://stackoverflow.com/a/4075045
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
if (mSaveKeyringParcel == null) {
|
||||
if (mSkpBuilder == null) {
|
||||
return false;
|
||||
} else {
|
||||
return super.isEnabled(position);
|
||||
@@ -370,10 +368,10 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
*
|
||||
* @see SaveKeyringParcel
|
||||
*
|
||||
* @param saveKeyringParcel The parcel to get info from, or null to leave edit mode.
|
||||
* @param builder The parcel to get info from, or null to leave edit mode.
|
||||
*/
|
||||
public void setEditMode(@Nullable SaveKeyringParcel saveKeyringParcel) {
|
||||
mSaveKeyringParcel = saveKeyringParcel;
|
||||
public void setEditMode(@Nullable SaveKeyringParcel.Builder builder) {
|
||||
mSkpBuilder = builder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -100,9 +100,9 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
|
||||
|
||||
String algorithmStr = KeyFormattingUtils.getAlgorithmInfo(
|
||||
mActivity,
|
||||
holder.mModel.mAlgorithm,
|
||||
holder.mModel.mKeySize,
|
||||
holder.mModel.mCurve
|
||||
holder.mModel.getAlgorithm(),
|
||||
holder.mModel.getKeySize(),
|
||||
holder.mModel.getCurve()
|
||||
);
|
||||
|
||||
boolean isMasterKey = mNewKeyring && position == 0;
|
||||
@@ -148,8 +148,8 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
|
||||
holder.vKeyId.setText(R.string.edit_key_new_subkey);
|
||||
holder.vKeyDetails.setText(algorithmStr);
|
||||
|
||||
if (holder.mModel.mExpiry != 0L) {
|
||||
Date expiryDate = new Date(holder.mModel.mExpiry * 1000);
|
||||
if (holder.mModel.getExpiry() != 0L) {
|
||||
Date expiryDate = new Date(holder.mModel.getExpiry() * 1000);
|
||||
Calendar expiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
expiryCal.setTime(expiryDate);
|
||||
// convert from UTC to time zone of device
|
||||
@@ -162,7 +162,7 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
|
||||
+ getContext().getString(R.string.none));
|
||||
}
|
||||
|
||||
int flags = holder.mModel.mFlags;
|
||||
int flags = holder.mModel.getFlags();
|
||||
if ((flags & KeyFlags.CERTIFY_OTHER) > 0) {
|
||||
holder.vCertifyIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
|
||||
@@ -32,9 +32,7 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewAnimator;
|
||||
|
||||
import org.openintents.openpgp.util.OpenPgpUtils;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
@@ -43,20 +41,18 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
|
||||
public class UserIdsAdapter extends UserAttributesAdapter {
|
||||
protected LayoutInflater mInflater;
|
||||
private SaveKeyringParcel mSaveKeyringParcel;
|
||||
private SaveKeyringParcel.Builder mSkpBuilder;
|
||||
private boolean mShowStatusImages;
|
||||
|
||||
public UserIdsAdapter(Context context, Cursor c, int flags,
|
||||
boolean showStatusImages, SaveKeyringParcel saveKeyringParcel) {
|
||||
public UserIdsAdapter(Context context, Cursor c, int flags, boolean showStatusImages) {
|
||||
super(context, c, flags);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
|
||||
mSaveKeyringParcel = saveKeyringParcel;
|
||||
mShowStatusImages = showStatusImages;
|
||||
}
|
||||
|
||||
public UserIdsAdapter(Context context, Cursor c, int flags) {
|
||||
this(context, c, flags, true, null);
|
||||
this(context, c, flags, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,11 +92,11 @@ public class UserIdsAdapter extends UserAttributesAdapter {
|
||||
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
|
||||
|
||||
// for edit key
|
||||
if (mSaveKeyringParcel != null) {
|
||||
boolean changeAnyPrimaryUserId = (mSaveKeyringParcel.mChangePrimaryUserId != null);
|
||||
boolean changeThisPrimaryUserId = (mSaveKeyringParcel.mChangePrimaryUserId != null
|
||||
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId));
|
||||
boolean revokeThisUserId = (mSaveKeyringParcel.mRevokeUserIds.contains(userId));
|
||||
if (mSkpBuilder != null) {
|
||||
String changePrimaryUserId = mSkpBuilder.getChangePrimaryUserId();
|
||||
boolean changeAnyPrimaryUserId = (changePrimaryUserId != null);
|
||||
boolean changeThisPrimaryUserId = (changeAnyPrimaryUserId && changePrimaryUserId.equals(userId));
|
||||
boolean revokeThisUserId = (mSkpBuilder.getMutableRevokeUserIds().contains(userId));
|
||||
|
||||
// only if primary user id will be changed
|
||||
// (this is not triggered if the user id is currently the primary one)
|
||||
@@ -161,8 +157,8 @@ public class UserIdsAdapter extends UserAttributesAdapter {
|
||||
String userId = mCursor.getString(INDEX_USER_ID);
|
||||
|
||||
boolean isRevokedPending = false;
|
||||
if (mSaveKeyringParcel != null) {
|
||||
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) {
|
||||
if (mSkpBuilder != null) {
|
||||
if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
|
||||
isRevokedPending = true;
|
||||
}
|
||||
|
||||
@@ -181,8 +177,8 @@ public class UserIdsAdapter extends UserAttributesAdapter {
|
||||
*
|
||||
* @param saveKeyringParcel The parcel to get info from, or null to leave edit mode.
|
||||
*/
|
||||
public void setEditMode(@Nullable SaveKeyringParcel saveKeyringParcel) {
|
||||
mSaveKeyringParcel = saveKeyringParcel;
|
||||
public void setEditMode(@Nullable SaveKeyringParcel.Builder saveKeyringParcel) {
|
||||
mSkpBuilder = saveKeyringParcel;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -323,7 +323,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
|
||||
}
|
||||
|
||||
public void cryptoOperation() {
|
||||
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
|
||||
}
|
||||
|
||||
public void onHandleResult(OperationResult result) {
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
|
||||
import org.sufficientlysecure.keychain.util.Choice;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -304,7 +305,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
||||
expiry = selectedCal.getTime().getTime() / 1000;
|
||||
}
|
||||
|
||||
SaveKeyringParcel.SubkeyAdd newSubkey = new SaveKeyringParcel.SubkeyAdd(
|
||||
SaveKeyringParcel.SubkeyAdd newSubkey = SubkeyAdd.createSubkeyAdd(
|
||||
algorithm, keySize, curve, flags, expiry
|
||||
);
|
||||
mAlgorithmSelectedListener.onAlgorithmSelected(newSubkey);
|
||||
|
||||
@@ -542,14 +542,14 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
|
||||
@Nullable
|
||||
@Override
|
||||
public Parcelable createOperationInput() {
|
||||
CertifyAction action = new CertifyAction(mMasterKeyId, null,
|
||||
CertifyAction action = CertifyAction.createForUserAttributes(mMasterKeyId,
|
||||
Collections.singletonList(mLinkedId.toUserAttribute()));
|
||||
|
||||
// fill values for this action
|
||||
CertifyActionsParcel parcel = new CertifyActionsParcel(mCertifyKeyId);
|
||||
parcel.mCertifyActions.addAll(Collections.singletonList(action));
|
||||
CertifyActionsParcel.Builder builder = CertifyActionsParcel.builder(mCertifyKeyId);
|
||||
builder.addActions(Collections.singletonList(action));
|
||||
|
||||
return parcel;
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -474,9 +474,8 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
||||
Bundle data = message.getData();
|
||||
|
||||
// use new passphrase!
|
||||
mChangeUnlockParcel = new ChangeUnlockParcel(
|
||||
mMasterKeyId,
|
||||
mFingerprint,
|
||||
mChangeUnlockParcel = ChangeUnlockParcel.createChangeUnlockParcel(
|
||||
mMasterKeyId, mFingerprint,
|
||||
(Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE)
|
||||
);
|
||||
|
||||
@@ -1176,7 +1175,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
||||
|
||||
@Override
|
||||
public ImportKeyringParcel createOperationInput() {
|
||||
return new ImportKeyringParcel(mKeyList, mKeyserver);
|
||||
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -143,7 +143,7 @@ public class ViewKeyFragment extends LoaderFragment implements LoaderManager.Loa
|
||||
mIsSecret = getArguments().getBoolean(ARG_IS_SECRET);
|
||||
|
||||
// load user ids after we know if it's a secret key
|
||||
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null);
|
||||
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret);
|
||||
mUserIds.setAdapter(mUserIdsAdapter);
|
||||
|
||||
// initialize loaders, which will take care of auto-refresh on change
|
||||
|
||||
@@ -210,15 +210,11 @@ public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragmen
|
||||
@Nullable
|
||||
@Override
|
||||
public Parcelable createOperationInput() {
|
||||
SaveKeyringParcel skp =
|
||||
new SaveKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint);
|
||||
|
||||
WrappedUserAttribute ua =
|
||||
LinkedAttribute.fromResource(mVerifiedResource).toUserAttribute();
|
||||
|
||||
skp.mAddUserAttribute.add(ua);
|
||||
|
||||
return skp;
|
||||
SaveKeyringParcel.Builder builder=
|
||||
SaveKeyringParcel.buildChangeKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint);
|
||||
WrappedUserAttribute ua = LinkedAttribute.fromResource(mVerifiedResource).toUserAttribute();
|
||||
builder.addUserAttribute(ua);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -96,7 +96,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
|
||||
|
||||
byte[] mFingerprint;
|
||||
long mMasterKeyId;
|
||||
private SaveKeyringParcel mSaveKeyringParcel;
|
||||
private SaveKeyringParcel.Builder mSkpBuilder;
|
||||
private TextView mLinkedIdTitle, mLinkedIdComment;
|
||||
private boolean mFinishOnStop;
|
||||
|
||||
@@ -405,13 +405,10 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
WrappedUserAttribute ua = LinkedAttribute.fromResource(resource).toUserAttribute();
|
||||
mSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint);
|
||||
mSaveKeyringParcel.mAddUserAttribute.add(ua);
|
||||
|
||||
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
|
||||
mSkpBuilder.addUserAttribute(ua);
|
||||
cryptoOperation();
|
||||
|
||||
}
|
||||
}, 250);
|
||||
|
||||
@@ -421,7 +418,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
|
||||
@Override
|
||||
public SaveKeyringParcel createOperationInput() {
|
||||
// if this is null, the cryptoOperation silently aborts - which is what we want in that case
|
||||
return mSaveKeyringParcel;
|
||||
return mSkpBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.sufficientlysecure.keychain.util;
|
||||
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import com.ryanharter.auto.value.parcel.TypeAdapter;
|
||||
|
||||
|
||||
public class ByteMapParcelAdapter implements TypeAdapter<Map<ByteBuffer,byte[]>> {
|
||||
@Override
|
||||
public Map<ByteBuffer, byte[]> fromParcel(Parcel source) {
|
||||
int count = source.readInt();
|
||||
Map<ByteBuffer,byte[]> result = new HashMap<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
byte[] key = source.createByteArray();
|
||||
byte[] value = source.createByteArray();
|
||||
result.put(ByteBuffer.wrap(key), value);
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toParcel(Map<ByteBuffer, byte[]> value, Parcel dest) {
|
||||
dest.writeInt(value.size());
|
||||
for (Map.Entry<ByteBuffer, byte[]> entry : value.entrySet()) {
|
||||
dest.writeByteArray(entry.getKey().array());
|
||||
dest.writeByteArray(entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public class EmailKeyHelper {
|
||||
|
||||
@Override
|
||||
public ImportKeyringParcel createOperationInput() {
|
||||
return new ImportKeyringParcel(mKeyList, mKeyserver);
|
||||
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import android.widget.EditText;
|
||||
|
||||
import org.bouncycastle.bcpg.S2K;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.pgp.ComparableS2K;
|
||||
import org.sufficientlysecure.keychain.pgp.ParcelableS2K;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -49,7 +49,7 @@ import java.util.Map.Entry;
|
||||
*/
|
||||
public class Passphrase implements Parcelable {
|
||||
private char[] mPassphrase;
|
||||
private HashMap<ComparableS2K, byte[]> mCachedSessionKeys;
|
||||
private HashMap<ParcelableS2K, byte[]> mCachedSessionKeys;
|
||||
|
||||
/**
|
||||
* According to http://stackoverflow.com/a/15844273 EditText is not using String internally
|
||||
@@ -104,7 +104,7 @@ public class Passphrase implements Parcelable {
|
||||
if (mCachedSessionKeys == null) {
|
||||
return null;
|
||||
}
|
||||
return mCachedSessionKeys.get(new ComparableS2K(keyEncryptionAlgorithm, s2k));
|
||||
return mCachedSessionKeys.get(ParcelableS2K.fromS2K(keyEncryptionAlgorithm, s2k));
|
||||
}
|
||||
|
||||
/** Adds a session key for a set of s2k parameters to this Passphrase object's
|
||||
@@ -116,7 +116,7 @@ public class Passphrase implements Parcelable {
|
||||
if (mCachedSessionKeys == null) {
|
||||
mCachedSessionKeys = new HashMap<>();
|
||||
}
|
||||
mCachedSessionKeys.put(new ComparableS2K(keyEncryptionAlgorithm, s2k), sessionKey);
|
||||
mCachedSessionKeys.put(ParcelableS2K.fromS2K(keyEncryptionAlgorithm, s2k), sessionKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,7 +184,7 @@ public class Passphrase implements Parcelable {
|
||||
}
|
||||
mCachedSessionKeys = new HashMap<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
ComparableS2K cachedS2K = source.readParcelable(getClass().getClassLoader());
|
||||
ParcelableS2K cachedS2K = source.readParcelable(getClass().getClassLoader());
|
||||
byte[] cachedSessionKey = source.createByteArray();
|
||||
mCachedSessionKeys.put(cachedS2K, cachedSessionKey);
|
||||
}
|
||||
@@ -197,7 +197,7 @@ public class Passphrase implements Parcelable {
|
||||
return;
|
||||
}
|
||||
dest.writeInt(mCachedSessionKeys.size());
|
||||
for (Entry<ComparableS2K,byte[]> entry : mCachedSessionKeys.entrySet()) {
|
||||
for (Entry<ParcelableS2K,byte[]> entry : mCachedSessionKeys.entrySet()) {
|
||||
dest.writeParcelable(entry.getKey(), 0);
|
||||
dest.writeByteArray(entry.getValue());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user