use autovalue for SaveKeyringParcel

This commit is contained in:
Vincent Breitmoser
2017-05-23 02:23:03 +02:00
parent 147e4dbee7
commit d58f1bd225
26 changed files with 816 additions and 812 deletions

View File

@@ -179,12 +179,12 @@ public final class Constants {
/** /**
* Default key configuration: 3072 bit RSA (certify, sign, encrypt) * Default key configuration: 3072 bit RSA (certify, sign, encrypt)
*/ */
public static void addDefaultSubkeys(SaveKeyringParcel saveKeyringParcel) { public static void addDefaultSubkeys(SaveKeyringParcel.Builder builder) {
saveKeyringParcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA, builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
3072, null, KeyFlags.CERTIFY_OTHER, 0L)); 3072, null, KeyFlags.CERTIFY_OTHER, 0L));
saveKeyringParcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA, builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
3072, null, KeyFlags.SIGN_DATA, 0L)); 3072, null, KeyFlags.SIGN_DATA, 0L));
saveKeyringParcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA, builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
3072, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); 3072, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L));
} }

View File

@@ -88,13 +88,13 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
new PgpKeyOperation(new ProgressScaler(mProgressable, 10, 60, 100), mCancelled); new PgpKeyOperation(new ProgressScaler(mProgressable, 10, 60, 100), mCancelled);
// If a key id is specified, fetch and edit // If a key id is specified, fetch and edit
if (saveParcel.mMasterKeyId != null) { if (saveParcel.getMasterKeyId() != null) {
try { try {
log.add(LogType.MSG_ED_FETCHING, 1, log.add(LogType.MSG_ED_FETCHING, 1,
KeyFormattingUtils.convertKeyIdToHex(saveParcel.mMasterKeyId)); KeyFormattingUtils.convertKeyIdToHex(saveParcel.getMasterKeyId()));
CanonicalizedSecretKeyRing secRing = CanonicalizedSecretKeyRing secRing =
mKeyRepository.getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId); mKeyRepository.getCanonicalizedSecretKeyRing(saveParcel.getMasterKeyId());
modifyResult = keyOperations.modifySecretKeyRing(secRing, cryptoInput, saveParcel); modifyResult = keyOperations.modifySecretKeyRing(secRing, cryptoInput, saveParcel);
if (modifyResult.isPending()) { if (modifyResult.isPending()) {
@@ -133,7 +133,7 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
// It's a success, so this must be non-null now // It's a success, so this must be non-null now
UncachedKeyRing ring = modifyResult.getRing(); UncachedKeyRing ring = modifyResult.getRing();
if (saveParcel.isUpload()) { if (saveParcel.isShouldUpload()) {
byte[] keyringBytes; byte[] keyringBytes;
try { try {
UncachedKeyRing publicKeyRing = ring.extractPublicKeyRing(); UncachedKeyRing publicKeyRing = ring.extractPublicKeyRing();
@@ -154,7 +154,7 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
if (uploadResult.isPending()) { if (uploadResult.isPending()) {
return new EditKeyResult(log, uploadResult); 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 // if atomic, update fail implies edit operation should also fail and not save
return new EditKeyResult(log, RequiredInputParcel.createRetryUploadOperation(), cryptoInput); return new EditKeyResult(log, RequiredInputParcel.createRetryUploadOperation(), cryptoInput);
} }

View File

@@ -71,17 +71,18 @@ public class RevokeOperation extends BaseReadWriteOperation<RevokeKeyringParcel>
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId); return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
} }
SaveKeyringParcel saveKeyringParcel = SaveKeyringParcel.Builder saveKeyringParcel =
new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint()); SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
// all revoke operations are made atomic as of now // all revoke operations are made atomic as of now
saveKeyringParcel.setUpdateOptions(revokeKeyringParcel.isShouldUpload(), true, saveKeyringParcel.setUpdateOptions(revokeKeyringParcel.isShouldUpload(), true,
revokeKeyringParcel.getKeyserver()); revokeKeyringParcel.getKeyserver());
saveKeyringParcel.mRevokeSubKeys.add(masterKeyId); saveKeyringParcel.addRevokeSubkey(masterKeyId);
EditKeyResult revokeAndUploadResult = new EditKeyOperation(mContext, EditKeyResult revokeAndUploadResult = new EditKeyOperation(mContext,
mKeyWritableRepository, mProgressable, mCancelled).execute(saveKeyringParcel, cryptoInputParcel); mKeyWritableRepository, mProgressable, mCancelled).execute(
saveKeyringParcel.build(), cryptoInputParcel);
if (revokeAndUploadResult.isPending()) { if (revokeAndUploadResult.isPending()) {
return revokeAndUploadResult; return revokeAndUploadResult;

View File

@@ -29,10 +29,10 @@ import java.security.NoSuchProviderException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.SignatureException; import java.security.SignatureException;
import java.security.spec.ECGenParameterSpec; import java.security.spec.ECGenParameterSpec;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Stack; import java.util.Stack;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -80,6 +80,7 @@ import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel; import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; 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.Curve;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
@@ -287,23 +288,23 @@ public class PgpKeyOperation {
progress(R.string.progress_building_key, 0); progress(R.string.progress_building_key, 0);
indent += 1; indent += 1;
if (saveParcel.mAddSubKeys.isEmpty()) { if (saveParcel.getAddSubKeys().isEmpty()) {
log.add(LogType.MSG_CR_ERROR_NO_MASTER, indent); log.add(LogType.MSG_CR_ERROR_NO_MASTER, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); 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); log.add(LogType.MSG_CR_ERROR_NO_USER_ID, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} }
SubkeyAdd add = saveParcel.mAddSubKeys.remove(0); SubkeyAdd certificationKey = saveParcel.getAddSubKeys().get(0);
if ((add.getFlags() & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) { if ((certificationKey.getFlags() & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
log.add(LogType.MSG_CR_ERROR_NO_CERTIFY, indent); log.add(LogType.MSG_CR_ERROR_NO_CERTIFY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} }
if (add.getExpiry() == null) { if (certificationKey.getExpiry() == null) {
log.add(LogType.MSG_CR_ERROR_NULL_EXPIRY, indent); log.add(LogType.MSG_CR_ERROR_NULL_EXPIRY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} }
@@ -311,7 +312,7 @@ public class PgpKeyOperation {
Date creationTime = new Date(); Date creationTime = new Date();
subProgressPush(10, 30); subProgressPush(10, 30);
PGPKeyPair keyPair = createKey(add, creationTime, log, indent); PGPKeyPair keyPair = createKey(certificationKey, creationTime, log, indent);
subProgressPop(); subProgressPop();
// return null if this failed (an error will already have been logged by createKey) // return null if this failed (an error will already have been logged by createKey)
@@ -337,9 +338,14 @@ public class PgpKeyOperation {
PGPSecretKeyRing sKR = new PGPSecretKeyRing( PGPSecretKeyRing sKR = new PGPSecretKeyRing(
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator()); 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); subProgressPush(50, 100);
CryptoInputParcel cryptoInput = CryptoInputParcel.createCryptoInputParcel(creationTime, new Passphrase("")); CryptoInputParcel cryptoInput = CryptoInputParcel.createCryptoInputParcel(creationTime, new Passphrase(""));
return internal(sKR, masterSecretKey, add.getFlags(), add.getExpiry(), cryptoInput, saveParcel, log, indent); return internal(sKR, masterSecretKey, certificationKey.getFlags(), certificationKey.getExpiry(), cryptoInput, saveParcel, log, indent);
} catch (PGPException e) { } catch (PGPException e) {
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent); log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
@@ -394,7 +400,7 @@ public class PgpKeyOperation {
progress(R.string.progress_building_key, 0); progress(R.string.progress_building_key, 0);
// Make sure this is called with a proper SaveKeyringParcel // 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); log.add(LogType.MSG_MF_ERROR_KEYID, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} }
@@ -404,75 +410,29 @@ public class PgpKeyOperation {
PGPSecretKey masterSecretKey = sKR.getSecretKey(); PGPSecretKey masterSecretKey = sKR.getSecretKey();
// Make sure the fingerprint matches // Make sure the fingerprint matches
if (saveParcel.mFingerprint == null || !Arrays.equals(saveParcel.mFingerprint, if (saveParcel.getFingerprint() == null || !Arrays.equals(saveParcel.getFingerprint(),
masterSecretKey.getPublicKey().getFingerprint())) { masterSecretKey.getPublicKey().getFingerprint())) {
log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent); log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} }
if (saveParcel.isEmpty()) { if (isParcelEmpty(saveParcel)) {
log.add(LogType.MSG_MF_ERROR_NOOP, indent); log.add(LogType.MSG_MF_ERROR_NOOP, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} }
// Ensure we don't have multiple keys for the same slot. saveParcel = parseSecurityTokenSerialNumberIntoSubkeyChanges(cryptoInput, saveParcel);
boolean hasSign = false;
boolean hasEncrypt = false;
boolean hasAuth = false;
for (SaveKeyringParcel.SubkeyChange change : new ArrayList<>(saveParcel.mChangeSubKeys)) {
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 (!checkCapabilitiesAreUnique(wsKR, saveParcel, log, indent)) {
if (serialNumber != null) { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
saveParcel.addOrReplaceSubkeyChange(
SubkeyChange.createSecurityTokenSerialNo(change.getSubKeyId(), serialNumber));
}
}
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 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 (isDummy(masterSecretKey) && ! saveParcel.isRestrictedOnly()) { if (isDummy(masterSecretKey) && ! isParcelRestrictedOnly(saveParcel)) {
log.add(LogType.MSG_EK_ERROR_DUMMY, indent); log.add(LogType.MSG_EK_ERROR_DUMMY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); 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); log.add(LogType.MSG_MF_RESTRICTED_MODE, indent);
return internalRestricted(sKR, saveParcel, log, indent + 1); return internalRestricted(sKR, saveParcel, log, indent + 1);
} }
@@ -496,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, private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
int masterKeyFlags, long masterKeyExpiry, int masterKeyFlags, long masterKeyExpiry,
CryptoInputParcel cryptoInput, CryptoInputParcel cryptoInput,
@@ -549,10 +573,11 @@ public class PgpKeyOperation {
// 2a. Add certificates for new user ids // 2a. Add certificates for new user ids
subProgressPush(15, 23); 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())); progress(R.string.progress_modify_adduid, (i - 1) * (100 / saveParcel.getAddUserIds().size()));
String userId = saveParcel.mAddUserIds.get(i); String userId = saveParcel.getAddUserIds().get(i);
log.add(LogType.MSG_MF_UID_ADD, indent, userId); log.add(LogType.MSG_MF_UID_ADD, indent, userId);
if ("".equals(userId)) { if ("".equals(userId)) {
@@ -583,8 +608,8 @@ public class PgpKeyOperation {
} }
// if it's supposed to be primary, we can do that here as well // if it's supposed to be primary, we can do that here as well
boolean isPrimary = saveParcel.mChangePrimaryUserId != null boolean isPrimary = changePrimaryUserId != null
&& userId.equals(saveParcel.mChangePrimaryUserId); && userId.equals(changePrimaryUserId);
// generate and add new certificate // generate and add new certificate
try { try {
PGPSignature cert = generateUserIdSignature( PGPSignature cert = generateUserIdSignature(
@@ -601,10 +626,10 @@ public class PgpKeyOperation {
// 2b. Add certificates for new user ids // 2b. Add certificates for new user ids
subProgressPush(23, 32); subProgressPush(23, 32);
for (int i = 0; i < saveParcel.mAddUserAttribute.size(); i++) { List<WrappedUserAttribute> addUserAttributes = saveParcel.getAddUserAttribute();
for (int i = 0; i < addUserAttributes.size(); i++) {
progress(R.string.progress_modify_adduat, (i - 1) * (100 / saveParcel.mAddUserAttribute.size())); progress(R.string.progress_modify_adduat, (i - 1) * (100 / addUserAttributes.size()));
WrappedUserAttribute attribute = saveParcel.mAddUserAttribute.get(i); WrappedUserAttribute attribute = addUserAttributes.get(i);
switch (attribute.getType()) { switch (attribute.getType()) {
// the 'none' type must not succeed // the 'none' type must not succeed
@@ -637,10 +662,10 @@ public class PgpKeyOperation {
// 2c. Add revocations for revoked user ids // 2c. Add revocations for revoked user ids
subProgressPush(32, 40); subProgressPush(32, 40);
for (int i = 0; i < saveParcel.mRevokeUserIds.size(); 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 / saveParcel.mRevokeUserIds.size())); progress(R.string.progress_modify_revokeuid, (i - 1) * (100 / revokeUserIds.size()));
String userId = saveParcel.mRevokeUserIds.get(i); String userId = revokeUserIds.get(i);
log.add(LogType.MSG_MF_UID_REVOKE, indent, userId); log.add(LogType.MSG_MF_UID_REVOKE, indent, userId);
// Make sure the user id exists (yes these are 10 LoC in Java!) // Make sure the user id exists (yes these are 10 LoC in Java!)
@@ -672,12 +697,12 @@ public class PgpKeyOperation {
subProgressPop(); subProgressPop();
// 3. If primary user id changed, generate new certificates for both old and new // 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); progress(R.string.progress_modify_primaryuid, 40);
// keep track if we actually changed one // keep track if we actually changed one
boolean ok = false; boolean ok = false;
log.add(LogType.MSG_MF_UID_PRIMARY, indent, saveParcel.mChangePrimaryUserId); log.add(LogType.MSG_MF_UID_PRIMARY, indent, changePrimaryUserId);
indent += 1; indent += 1;
// we work on the modifiedPublicKey here, to respect new or newly revoked uids // we work on the modifiedPublicKey here, to respect new or newly revoked uids
@@ -718,7 +743,7 @@ public class PgpKeyOperation {
// we definitely should not update certifications of revoked keys, so just leave it. // we definitely should not update certifications of revoked keys, so just leave it.
if (isRevoked) { if (isRevoked) {
// revoked user ids cannot be primary! // revoked user ids cannot be primary!
if (userId.equals(saveParcel.mChangePrimaryUserId)) { if (userId.equals(changePrimaryUserId)) {
log.add(LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent); log.add(LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} }
@@ -729,7 +754,7 @@ public class PgpKeyOperation {
if (currentCert.getHashedSubPackets() != null if (currentCert.getHashedSubPackets() != null
&& currentCert.getHashedSubPackets().isPrimaryUserID()) { && currentCert.getHashedSubPackets().isPrimaryUserID()) {
// if it's the one we want, just leave it as is // if it's the one we want, just leave it as is
if (userId.equals(saveParcel.mChangePrimaryUserId)) { if (userId.equals(changePrimaryUserId)) {
ok = true; ok = true;
continue; continue;
} }
@@ -755,7 +780,7 @@ public class PgpKeyOperation {
// if we are here, this is not currently a primary user id // if we are here, this is not currently a primary user id
// if it should be // if it should be
if (userId.equals(saveParcel.mChangePrimaryUserId)) { if (userId.equals(changePrimaryUserId)) {
// add shiny new primary user id certificate // add shiny new primary user id certificate
log.add(LogType.MSG_MF_PRIMARY_NEW, indent); log.add(LogType.MSG_MF_PRIMARY_NEW, indent);
modifiedPublicKey = PGPPublicKey.removeCertification( modifiedPublicKey = PGPPublicKey.removeCertification(
@@ -803,10 +828,11 @@ public class PgpKeyOperation {
// 4a. For each subkey change, generate new subkey binding certificate // 4a. For each subkey change, generate new subkey binding certificate
subProgressPush(50, 60); 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())); progress(R.string.progress_modify_subkeychange, (i-1) * (100 / changeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i); SaveKeyringParcel.SubkeyChange change = changeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_CHANGE, log.add(LogType.MSG_MF_SUBKEY_CHANGE,
indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId())); indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
@@ -944,10 +970,10 @@ public class PgpKeyOperation {
// 4b. For each subkey revocation, generate new subkey revocation certificate // 4b. For each subkey revocation, generate new subkey revocation certificate
subProgressPush(60, 65); subProgressPush(60, 65);
for (int i = 0; i < saveParcel.mRevokeSubKeys.size(); 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 / saveParcel.mRevokeSubKeys.size())); progress(R.string.progress_modify_subkeyrevoke, (i-1) * (100 / revokeSubKeys.size()));
long revocation = saveParcel.mRevokeSubKeys.get(i); long revocation = revokeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_REVOKE, log.add(LogType.MSG_MF_SUBKEY_REVOKE,
indent, KeyFormattingUtils.convertKeyIdToHex(revocation)); indent, KeyFormattingUtils.convertKeyIdToHex(revocation));
@@ -976,16 +1002,16 @@ public class PgpKeyOperation {
// 5. Generate and add new subkeys // 5. Generate and add new subkeys
subProgressPush(70, 90); 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. // Check if we were cancelled - again. This operation is expensive so we do it each loop.
if (checkCancelled()) { if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED, indent); log.add(LogType.MSG_OPERATION_CANCELLED, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null);
} }
progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / saveParcel.mAddSubKeys.size())); progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / addSubKeys.size()));
SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i); SaveKeyringParcel.SubkeyAdd add = addSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_NEW, indent, log.add(LogType.MSG_MF_SUBKEY_NEW, indent,
KeyFormattingUtils.getAlgorithmInfo(add.getAlgorithm(), add.getKeySize(), add.getCurve()) ); KeyFormattingUtils.getAlgorithmInfo(add.getAlgorithm(), add.getKeySize(), add.getCurve()) );
@@ -1006,8 +1032,8 @@ public class PgpKeyOperation {
// generate a new secret key (privkey only for now) // generate a new secret key (privkey only for now)
subProgressPush( subProgressPush(
(i-1) * (100 / saveParcel.mAddSubKeys.size()), (i-1) * (100 / addSubKeys.size()),
i * (100 / saveParcel.mAddSubKeys.size()) i * (100 / addSubKeys.size())
); );
PGPKeyPair keyPair = createKey(add, cryptoInput.getSignatureTime(), log, indent); PGPKeyPair keyPair = createKey(add, cryptoInput.getSignatureTime(), log, indent);
subProgressPop(); subProgressPop();
@@ -1060,13 +1086,13 @@ public class PgpKeyOperation {
} }
// 6. If requested, change passphrase // 6. If requested, change passphrase
if (saveParcel.getChangeUnlockParcel() != null) { if (saveParcel.getNewUnlock() != null) {
progress(R.string.progress_modify_passphrase, 90); progress(R.string.progress_modify_passphrase, 90);
log.add(LogType.MSG_MF_PASSPHRASE, indent); log.add(LogType.MSG_MF_PASSPHRASE, indent);
indent += 1; indent += 1;
sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(), sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(),
saveParcel.getChangeUnlockParcel().getNewPassphrase(), log, indent); saveParcel.getNewUnlock().getNewPassphrase(), log, indent);
if (sKR == null) { if (sKR == null) {
// The error has been logged above, just return a bad state // The error has been logged above, just return a bad state
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
@@ -1076,21 +1102,21 @@ public class PgpKeyOperation {
} }
// 7. if requested, change PIN and/or Admin PIN on security token // 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); progress(R.string.progress_modify_pin, 90);
log.add(LogType.MSG_MF_PIN, indent); log.add(LogType.MSG_MF_PIN, indent);
indent += 1; indent += 1;
nfcKeyToCardOps.setPin(saveParcel.mSecurityTokenPin); nfcKeyToCardOps.setPin(saveParcel.getSecurityTokenPin());
indent -= 1; indent -= 1;
} }
if (saveParcel.mSecurityTokenAdminPin != null) { if (saveParcel.getSecurityTokenAdminPin() != null) {
progress(R.string.progress_modify_admin_pin, 90); progress(R.string.progress_modify_admin_pin, 90);
log.add(LogType.MSG_MF_ADMIN_PIN, indent); log.add(LogType.MSG_MF_ADMIN_PIN, indent);
indent += 1; indent += 1;
nfcKeyToCardOps.setAdminPin(saveParcel.mSecurityTokenAdminPin); nfcKeyToCardOps.setAdminPin(saveParcel.getSecurityTokenAdminPin());
indent -= 1; indent -= 1;
} }
@@ -1141,7 +1167,7 @@ public class PgpKeyOperation {
progress(R.string.progress_modify, 0); progress(R.string.progress_modify, 0);
// Make sure the saveParcel includes only operations available without passphrase! // Make sure the saveParcel includes only operations available without passphrase!
if (!saveParcel.isRestrictedOnly()) { if (!isParcelRestrictedOnly(saveParcel)) {
log.add(LogType.MSG_MF_ERROR_RESTRICTED, indent); log.add(LogType.MSG_MF_ERROR_RESTRICTED, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} }
@@ -1155,10 +1181,10 @@ public class PgpKeyOperation {
// The only operation we can do here: // The only operation we can do here:
// 4a. Strip secret keys, or change their protection mode (stripped/divert-to-card) // 4a. Strip secret keys, or change their protection mode (stripped/divert-to-card)
subProgressPush(50, 60); 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())); progress(R.string.progress_modify_subkeychange, (i - 1) * (100 / changeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i); SaveKeyringParcel.SubkeyChange change = changeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_CHANGE, log.add(LogType.MSG_MF_SUBKEY_CHANGE,
indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId())); indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
@@ -1700,4 +1726,31 @@ public class PgpKeyOperation {
return true; 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();
}
} }

View File

@@ -86,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 X9ECParameters params = NISTNamedCurves.getByOID(mECCurveOID);
final ECCurve curve = params.getCurve(); final ECCurve curve = params.getCurve();
@@ -107,7 +107,6 @@ public class ECKeyFormat extends KeyFormat {
throw new IllegalArgumentException("Unsupported curve " + mECCurveOID); throw new IllegalArgumentException("Unsupported curve " + mECCurveOID);
} }
keyring.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(algo, builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(algo, curve.getFieldSize(), scurve, keyFlags, 0L));
curve.getFieldSize(), scurve, keyFlags, 0L));
} }
} }

View File

@@ -94,6 +94,6 @@ public abstract class KeyFormat {
throw new IllegalArgumentException("Unsupported Algorithm id " + t); throw new IllegalArgumentException("Unsupported Algorithm id " + t);
} }
public abstract void addToSaveKeyringParcel(SaveKeyringParcel keyring, int keyFlags); public abstract void addToSaveKeyringParcel(SaveKeyringParcel.Builder builder, int keyFlags);
} }

View File

@@ -86,8 +86,8 @@ public class RSAKeyFormat extends KeyFormat {
} }
} }
public void addToSaveKeyringParcel(SaveKeyringParcel keyring, int keyFlags) { public void addToSaveKeyringParcel(SaveKeyringParcel.Builder builder, int keyFlags) {
keyring.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA, builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
mModulusLength, null, keyFlags, 0L)); mModulusLength, null, keyFlags, 0L));
} }
} }

View File

@@ -18,18 +18,20 @@
package org.sufficientlysecure.keychain.service; package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import android.os.Parcelable; import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue; import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver; import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.Serializable;
import java.util.ArrayList;
/** /**
* This class is a a transferable representation for a collection of changes * This class is a a transferable representation for a collection of changes
* to be done on a keyring. * to be done on a keyring.
@@ -45,107 +47,183 @@ import java.util.ArrayList;
* error in any included operation (for example revocation of a non-existent * error in any included operation (for example revocation of a non-existent
* subkey) will cause the operation as a whole to fail. * 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 // 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. // the key fingerprint, for safety. MUST be null for a new key.
public byte[] mFingerprint; @Nullable
public abstract byte[] getFingerprint();
public ArrayList<String> mAddUserIds; public abstract List<String> getAddUserIds();
public ArrayList<WrappedUserAttribute> mAddUserAttribute; public abstract List<WrappedUserAttribute> getAddUserAttribute();
public ArrayList<SubkeyAdd> mAddSubKeys; public abstract List<SubkeyAdd> getAddSubKeys();
public ArrayList<SubkeyChange> mChangeSubKeys; public abstract List<SubkeyChange> getChangeSubKeys();
public String mChangePrimaryUserId; @Nullable
public abstract String getChangePrimaryUserId();
public ArrayList<String> mRevokeUserIds; public abstract List<String> getRevokeUserIds();
public ArrayList<Long> mRevokeSubKeys; public abstract List<Long> getRevokeSubKeys();
// if these are non-null, PINs will be changed on the token // if these are non-null, PINs will be changed on the token
public Passphrase mSecurityTokenPin; @Nullable
public Passphrase mSecurityTokenAdminPin; public abstract Passphrase getSecurityTokenPin();
@Nullable
public abstract Passphrase getSecurityTokenAdminPin();
// private because they have to be set together with setUpdateOptions public abstract boolean isShouldUpload();
private boolean mUpload; public abstract boolean isShouldUploadAtomic();
private boolean mUploadAtomic; @Nullable
private ParcelableHkpKeyserver mKeyserver; public abstract ParcelableHkpKeyserver getUploadKeyserver();
// private because we have to set other details like key id @Nullable
private ChangeUnlockParcel mNewUnlock; public abstract ChangeUnlockParcel getNewUnlock();
public SaveKeyringParcel() { public static Builder buildNewKeyringParcel() {
reset(); return new AutoValue_SaveKeyringParcel.Builder()
.setShouldUpload(false)
.setShouldUploadAtomic(false);
} }
public SaveKeyringParcel(long masterKeyId, byte[] fingerprint) { public static Builder buildChangeKeyringParcel(long masterKeyId, byte[] fingerprint) {
this(); return buildNewKeyringParcel()
mMasterKeyId = masterKeyId; .setMasterKeyId(masterKeyId)
mFingerprint = fingerprint; .setFingerprint(fingerprint);
} }
public void reset() { abstract Builder toBuilder();
mNewUnlock = null;
mAddUserIds = new ArrayList<>(); public static Builder buildUpon(SaveKeyringParcel saveKeyringParcel) {
mAddUserAttribute = new ArrayList<>(); SaveKeyringParcel.Builder builder = saveKeyringParcel.toBuilder();
mAddSubKeys = new ArrayList<>(); builder.addUserIds.addAll(saveKeyringParcel.getAddUserIds());
mChangePrimaryUserId = null; builder.revokeUserIds.addAll(saveKeyringParcel.getRevokeUserIds());
mChangeSubKeys = new ArrayList<>(); builder.addUserAttribute.addAll(saveKeyringParcel.getAddUserAttribute());
mRevokeUserIds = new ArrayList<>(); builder.addSubKeys.addAll(saveKeyringParcel.getAddSubKeys());
mRevokeSubKeys = new ArrayList<>(); builder.changeSubKeys.addAll(saveKeyringParcel.getChangeSubKeys());
mSecurityTokenPin = null; builder.revokeSubKeys.addAll(saveKeyringParcel.getRevokeSubKeys());
mSecurityTokenAdminPin = null; return builder;
mUpload = false;
mUploadAtomic = false;
mKeyserver = null;
} }
public void setUpdateOptions(boolean upload, boolean uploadAtomic, ParcelableHkpKeyserver keyserver) { @AutoValue.Builder
mUpload = upload; public static abstract class Builder {
mUploadAtomic = uploadAtomic; private ArrayList<String> addUserIds = new ArrayList<>();
mKeyserver = keyserver; 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() { public abstract Builder setChangePrimaryUserId(String changePrimaryUserId);
return mNewUnlock; public abstract Builder setSecurityTokenPin(Passphrase securityTokenPin);
} public abstract Builder setSecurityTokenAdminPin(Passphrase securityTokenAdminPin);
public abstract Builder setNewUnlock(ChangeUnlockParcel newUnlock);
public boolean isUpload() { public abstract Long getMasterKeyId();
return mUpload; public abstract byte[] getFingerprint();
} public abstract String getChangePrimaryUserId();
public boolean isUploadAtomic() {
return mUploadAtomic;
}
public ParcelableHkpKeyserver getUploadKeyserver() { public ArrayList<SubkeyAdd> getMutableAddSubKeys() {
return mKeyserver; return addSubKeys;
} }
public ArrayList<String> getMutableAddUserIds() {
public boolean isEmpty() { return addUserIds;
return isRestrictedOnly() && mChangeSubKeys.isEmpty(); }
} public ArrayList<Long> getMutableRevokeSubKeys() {
return revokeSubKeys;
/** Returns true iff this parcel does not contain any operations which require a passphrase. */ }
public boolean isRestrictedOnly() { public ArrayList<String> getMutableRevokeUserIds() {
if (mNewUnlock != null || !mAddUserIds.isEmpty() || !mAddUserAttribute.isEmpty() return revokeUserIds;
|| !mAddSubKeys.isEmpty() || mChangePrimaryUserId != null || !mRevokeUserIds.isEmpty()
|| !mRevokeSubKeys.isEmpty()) {
return false;
} }
for (SubkeyChange change : mChangeSubKeys) { abstract Builder setMasterKeyId(Long masterKeyId);
if (change.getRecertify() || change.getFlags() != null || change.getExpiry() != null abstract Builder setFingerprint(byte[] fingerprint);
|| change.getMoveKeyToSecurityToken()) { abstract Builder setAddUserIds(List<String> addUserIds);
return false; 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, // performance gain for using Parcelable here would probably be negligible,
@@ -208,114 +286,6 @@ public class SaveKeyringParcel implements Parcelable {
} }
} }
public SubkeyChange getSubkeyChange(long keyId) {
for (SubkeyChange subkeyChange : mChangeSubKeys) {
if (subkeyChange.getSubKeyId() == keyId) {
return subkeyChange;
}
}
return null;
}
public void addOrReplaceSubkeyChange(SubkeyChange change) {
SubkeyChange foundSubkeyChange = getSubkeyChange(change.getSubKeyId());
if (foundSubkeyChange != null) {
mChangeSubKeys.remove(foundSubkeyChange);
}
mChangeSubKeys.add(change);
}
public void removeSubkeyChange(SubkeyChange change) {
mChangeSubKeys.remove(change);
}
@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 // All supported algorithms
public enum Algorithm { public enum Algorithm {
RSA, DSA, ELGAMAL, ECDSA, ECDH RSA, DSA, ELGAMAL, ECDSA, ECDH
@@ -330,7 +300,4 @@ public class SaveKeyringParcel implements Parcelable {
// (adding support would be trivial though -> JcaPGPKeyConverter.java:190) // (adding support would be trivial though -> JcaPGPKeyConverter.java:190)
// BRAINPOOL_P256, BRAINPOOL_P384, BRAINPOOL_P512 // BRAINPOOL_P256, BRAINPOOL_P384, BRAINPOOL_P512
} }
} }

View File

@@ -295,7 +295,7 @@ public class CreateKeyFinalFragment extends Fragment {
} }
private static SaveKeyringParcel createDefaultSaveKeyringParcel(CreateKeyActivity createKeyActivity) { private static SaveKeyringParcel createDefaultSaveKeyringParcel(CreateKeyActivity createKeyActivity) {
SaveKeyringParcel saveKeyringParcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
if (createKeyActivity.mCreateSecurityToken) { if (createKeyActivity.mCreateSecurityToken) {
if (createKeyActivity.mSecurityTokenSign == null) { if (createKeyActivity.mSecurityTokenSign == null) {
@@ -303,38 +303,40 @@ public class CreateKeyFinalFragment extends Fragment {
createKeyActivity.mSecurityTokenDec = Constants.SECURITY_TOKEN_V2_DEC; createKeyActivity.mSecurityTokenDec = Constants.SECURITY_TOKEN_V2_DEC;
createKeyActivity.mSecurityTokenAuth = Constants.SECURITY_TOKEN_V2_AUTH; createKeyActivity.mSecurityTokenAuth = Constants.SECURITY_TOKEN_V2_AUTH;
} }
createKeyActivity.mSecurityTokenSign.addToSaveKeyringParcel(saveKeyringParcel, KeyFlags.SIGN_DATA | KeyFlags.CERTIFY_OTHER); createKeyActivity.mSecurityTokenSign.addToSaveKeyringParcel(
createKeyActivity.mSecurityTokenDec.addToSaveKeyringParcel(saveKeyringParcel, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE); builder, KeyFlags.SIGN_DATA | KeyFlags.CERTIFY_OTHER);
createKeyActivity.mSecurityTokenAuth.addToSaveKeyringParcel(saveKeyringParcel, KeyFlags.AUTHENTICATION); createKeyActivity.mSecurityTokenDec.addToSaveKeyringParcel(
builder, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
createKeyActivity.mSecurityTokenAuth.addToSaveKeyringParcel(builder, KeyFlags.AUTHENTICATION);
// use empty passphrase // use empty passphrase
saveKeyringParcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase())); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase()));
} else { } else {
Constants.addDefaultSubkeys(saveKeyringParcel); Constants.addDefaultSubkeys(builder);
if (createKeyActivity.mPassphrase != null) { if (createKeyActivity.mPassphrase != null) {
saveKeyringParcel.setNewUnlock( builder.setNewUnlock(
ChangeUnlockParcel.createUnLockParcelForNewKey(createKeyActivity.mPassphrase)); ChangeUnlockParcel.createUnLockParcelForNewKey(createKeyActivity.mPassphrase));
} else { } else {
saveKeyringParcel.setNewUnlock(null); builder.setNewUnlock(null);
} }
} }
String userId = KeyRing.createUserId( String userId = KeyRing.createUserId(
new OpenPgpUtils.UserId(createKeyActivity.mName, createKeyActivity.mEmail, null) new OpenPgpUtils.UserId(createKeyActivity.mName, createKeyActivity.mEmail, null)
); );
saveKeyringParcel.mAddUserIds.add(userId); builder.addUserId(userId);
saveKeyringParcel.mChangePrimaryUserId = userId; builder.setChangePrimaryUserId(userId);
if (createKeyActivity.mAdditionalEmails != null if (createKeyActivity.mAdditionalEmails != null
&& createKeyActivity.mAdditionalEmails.size() > 0) { && createKeyActivity.mAdditionalEmails.size() > 0) {
for (String email : createKeyActivity.mAdditionalEmails) { for (String email : createKeyActivity.mAdditionalEmails) {
String thisUserId = KeyRing.createUserId( String thisUserId = KeyRing.createUserId(
new OpenPgpUtils.UserId(createKeyActivity.mName, email, null) new OpenPgpUtils.UserId(createKeyActivity.mName, email, null)
); );
saveKeyringParcel.mAddUserIds.add(thisUserId); builder.addUserId(thisUserId);
} }
} }
return saveKeyringParcel; return builder.build();
} }
private void checkEmailValidity() { private void checkEmailValidity() {
@@ -427,11 +429,11 @@ public class CreateKeyFinalFragment extends Fragment {
private void moveToCard(final EditKeyResult saveKeyResult) { private void moveToCard(final EditKeyResult saveKeyResult) {
CreateKeyActivity activity = (CreateKeyActivity) getActivity(); CreateKeyActivity activity = (CreateKeyActivity) getActivity();
final SaveKeyringParcel changeKeyringParcel; SaveKeyringParcel.Builder builder;
CachedPublicKeyRing key = (KeyRepository.createDatabaseInteractor(getContext())) CachedPublicKeyRing key = (KeyRepository.createDatabaseInteractor(getContext()))
.getCachedPublicKeyRing(saveKeyResult.mMasterKeyId); .getCachedPublicKeyRing(saveKeyResult.mMasterKeyId);
try { try {
changeKeyringParcel = new SaveKeyringParcel(key.getMasterKeyId(), key.getFingerprint()); builder = SaveKeyringParcel.buildChangeKeyringParcel(key.getMasterKeyId(), key.getFingerprint());
} catch (PgpKeyNotFoundException e) { } catch (PgpKeyNotFoundException e) {
Log.e(Constants.TAG, "Key that should be moved to Security Token not found in database!"); Log.e(Constants.TAG, "Key that should be moved to Security Token not found in database!");
return; return;
@@ -439,13 +441,13 @@ public class CreateKeyFinalFragment extends Fragment {
// define subkeys that should be moved to the card // define subkeys that should be moved to the card
Cursor cursor = activity.getContentResolver().query( Cursor cursor = activity.getContentResolver().query(
KeychainContract.Keys.buildKeysUri(changeKeyringParcel.mMasterKeyId), KeychainContract.Keys.buildKeysUri(builder.getMasterKeyId()),
new String[]{KeychainContract.Keys.KEY_ID,}, null, null, null new String[]{KeychainContract.Keys.KEY_ID,}, null, null, null
); );
try { try {
while (cursor != null && cursor.moveToNext()) { while (cursor != null && cursor.moveToNext()) {
long subkeyId = cursor.getLong(0); long subkeyId = cursor.getLong(0);
changeKeyringParcel.mChangeSubKeys.add(SubkeyChange.createMoveToSecurityTokenChange(subkeyId)); builder.addOrReplaceSubkeyChange(SubkeyChange.createMoveToSecurityTokenChange(subkeyId));
} }
} finally { } finally {
if (cursor != null) { if (cursor != null) {
@@ -454,15 +456,17 @@ public class CreateKeyFinalFragment extends Fragment {
} }
// define new PIN and Admin PIN for the card // define new PIN and Admin PIN for the card
changeKeyringParcel.mSecurityTokenPin = activity.mSecurityTokenPin; builder.setSecurityTokenPin(activity.mSecurityTokenPin);
changeKeyringParcel.mSecurityTokenAdminPin = activity.mSecurityTokenAdminPin; builder.setSecurityTokenAdminPin(activity.mSecurityTokenAdminPin);
final SaveKeyringParcel saveKeyringParcel = builder.build();
CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult> callback CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult> callback
= new CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult>() { = new CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult>() {
@Override @Override
public SaveKeyringParcel createOperationInput() { public SaveKeyringParcel createOperationInput() {
return changeKeyringParcel; return saveKeyringParcel;
} }
@Override @Override

View File

@@ -82,7 +82,7 @@ public class EditIdentitiesFragment extends Fragment
private Uri mDataUri; private Uri mDataUri;
private SaveKeyringParcel mSaveKeyringParcel; private SaveKeyringParcel.Builder mSkpBuilder;
private CryptoOperationHelper<SaveKeyringParcel, EditKeyResult> mEditOpHelper; private CryptoOperationHelper<SaveKeyringParcel, EditKeyResult> mEditOpHelper;
private CryptoOperationHelper<UploadKeyringParcel, UploadResult> mUploadOpHelper; private CryptoOperationHelper<UploadKeyringParcel, UploadResult> mUploadOpHelper;
@@ -180,7 +180,7 @@ public class EditIdentitiesFragment extends Fragment
return; return;
} }
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint()); mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback(); mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback();
} catch (PgpKeyNotFoundException | NotFoundException e) { } catch (PgpKeyNotFoundException | NotFoundException e) {
@@ -193,11 +193,11 @@ public class EditIdentitiesFragment extends Fragment
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditIdentitiesFragment.this); getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditIdentitiesFragment.this);
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0); mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
mUserIdsAdapter.setEditMode(mSaveKeyringParcel); mUserIdsAdapter.setEditMode(mSkpBuilder);
mUserIdsList.setAdapter(mUserIdsAdapter); mUserIdsList.setAdapter(mUserIdsAdapter);
// TODO: SaveParcel from savedInstance?! // TODO: SaveParcel from savedInstance?!
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, false); mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), false);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
} }
@@ -266,23 +266,23 @@ public class EditIdentitiesFragment extends Fragment
switch (message.what) { switch (message.what) {
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID: case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
// toggle // toggle
if (mSaveKeyringParcel.mChangePrimaryUserId != null if (mSkpBuilder.getChangePrimaryUserId() != null
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { && mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mSaveKeyringParcel.mChangePrimaryUserId = null; mSkpBuilder.setChangePrimaryUserId(null);
} else { } else {
mSaveKeyringParcel.mChangePrimaryUserId = userId; mSkpBuilder.setChangePrimaryUserId(userId);
} }
break; break;
case EditUserIdDialogFragment.MESSAGE_REVOKE: case EditUserIdDialogFragment.MESSAGE_REVOKE:
// toggle // toggle
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) { if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
mSaveKeyringParcel.mRevokeUserIds.remove(userId); mSkpBuilder.removeRevokeUserId(userId);
} else { } else {
mSaveKeyringParcel.mRevokeUserIds.add(userId); mSkpBuilder.addRevokeUserId(userId);
// not possible to revoke and change to primary user id // not possible to revoke and change to primary user id
if (mSaveKeyringParcel.mChangePrimaryUserId != null if (mSkpBuilder.getChangePrimaryUserId() != null
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { && mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mSaveKeyringParcel.mChangePrimaryUserId = null; mSkpBuilder.setChangePrimaryUserId(null);
} }
} }
break; break;
@@ -339,7 +339,7 @@ public class EditIdentitiesFragment extends Fragment
= new CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult>() { = new CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult>() {
@Override @Override
public SaveKeyringParcel createOperationInput() { public SaveKeyringParcel createOperationInput() {
return mSaveKeyringParcel; return mSkpBuilder.build();
} }
@Override @Override

View File

@@ -100,7 +100,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
private Uri mDataUri; private Uri mDataUri;
private SaveKeyringParcel mSaveKeyringParcel; private SaveKeyringParcel.Builder mSkpBuilder;
private String mPrimaryUserId; private String mPrimaryUserId;
@@ -184,13 +184,13 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
} }
private void loadSaveKeyringParcel(SaveKeyringParcel saveKeyringParcel) { private void loadSaveKeyringParcel(SaveKeyringParcel saveKeyringParcel) {
mSaveKeyringParcel = saveKeyringParcel; mSkpBuilder = SaveKeyringParcel.buildUpon(saveKeyringParcel);
mPrimaryUserId = saveKeyringParcel.mChangePrimaryUserId; mPrimaryUserId = saveKeyringParcel.getChangePrimaryUserId();
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, true); mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), true);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys, true); mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSkpBuilder.getMutableAddSubKeys(), true);
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter); mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
} }
@@ -213,7 +213,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
return; return;
} }
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint()); mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback(); mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback();
} catch (PgpKeyNotFoundException | NotFoundException e) { } catch (PgpKeyNotFoundException | NotFoundException e) {
@@ -227,18 +227,18 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this); getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this);
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0); mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
mUserIdsAdapter.setEditMode(mSaveKeyringParcel); mUserIdsAdapter.setEditMode(mSkpBuilder);
mUserIdsList.setAdapter(mUserIdsAdapter); mUserIdsList.setAdapter(mUserIdsAdapter);
// TODO: SaveParcel from savedInstance?! // TODO: SaveParcel from savedInstance?!
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, false); mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), false);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0); mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0);
mSubkeysAdapter.setEditMode(mSaveKeyringParcel); mSubkeysAdapter.setEditMode(mSkpBuilder);
mSubkeysList.setAdapter(mSubkeysAdapter); mSubkeysList.setAdapter(mSubkeysAdapter);
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys, false); mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSkpBuilder.getMutableAddSubKeys(), false);
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter); mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
} }
@@ -341,8 +341,8 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
Bundle data = message.getData(); Bundle data = message.getData();
// cache new returned passphrase! // cache new returned passphrase!
mSaveKeyringParcel.setNewUnlock(ChangeUnlockParcel.createChangeUnlockParcel( mSkpBuilder.setNewUnlock(ChangeUnlockParcel.createChangeUnlockParcel(
mSaveKeyringParcel.mMasterKeyId, mSaveKeyringParcel.mFingerprint, mSkpBuilder.getMasterKeyId(), mSkpBuilder.getFingerprint(),
(Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE))); (Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE)));
} }
} }
@@ -368,23 +368,23 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
switch (message.what) { switch (message.what) {
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID: case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
// toggle // toggle
if (mSaveKeyringParcel.mChangePrimaryUserId != null String changePrimaryUserId = mSkpBuilder.getChangePrimaryUserId();
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { if (changePrimaryUserId != null && changePrimaryUserId.equals(userId)) {
mSaveKeyringParcel.mChangePrimaryUserId = null; mSkpBuilder.setChangePrimaryUserId(null);
} else { } else {
mSaveKeyringParcel.mChangePrimaryUserId = userId; mSkpBuilder.setChangePrimaryUserId(userId);
} }
break; break;
case EditUserIdDialogFragment.MESSAGE_REVOKE: case EditUserIdDialogFragment.MESSAGE_REVOKE:
// toggle // toggle
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) { if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
mSaveKeyringParcel.mRevokeUserIds.remove(userId); mSkpBuilder.removeRevokeUserId(userId);
} else { } else {
mSaveKeyringParcel.mRevokeUserIds.add(userId); mSkpBuilder.addRevokeUserId(userId);
// not possible to revoke and change to primary user id // not possible to revoke and change to primary user id
if (mSaveKeyringParcel.mChangePrimaryUserId != null if (mSkpBuilder.getChangePrimaryUserId() != null
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { && mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mSaveKeyringParcel.mChangePrimaryUserId = null; mSkpBuilder.setChangePrimaryUserId(null);
} }
} }
break; break;
@@ -417,10 +417,10 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
break; break;
case EditSubkeyDialogFragment.MESSAGE_REVOKE: case EditSubkeyDialogFragment.MESSAGE_REVOKE:
// toggle // toggle
if (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId)) { if (mSkpBuilder.getMutableRevokeSubKeys().contains(keyId)) {
mSaveKeyringParcel.mRevokeSubKeys.remove(keyId); mSkpBuilder.removeRevokeSubkey(keyId);
} else { } else {
mSaveKeyringParcel.mRevokeSubKeys.add(keyId); mSkpBuilder.addRevokeSubkey(keyId);
} }
break; break;
case EditSubkeyDialogFragment.MESSAGE_STRIP: { case EditSubkeyDialogFragment.MESSAGE_STRIP: {
@@ -430,11 +430,11 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
break; break;
} }
SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId); SubkeyChange change = mSkpBuilder.getSubkeyChange(keyId);
if (change == null || !change.getDummyStrip()) { if (change == null || !change.getDummyStrip()) {
mSaveKeyringParcel.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId)); mSkpBuilder.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId));
} else { } else {
mSaveKeyringParcel.removeSubkeyChange(change); mSkpBuilder.removeSubkeyChange(change);
} }
break; break;
} }
@@ -474,13 +474,13 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
break; break;
} }
SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId); SubkeyChange change = mSkpBuilder.getSubkeyChange(keyId);
if (change == null || !change.getMoveKeyToSecurityToken()) { if (change == null || !change.getMoveKeyToSecurityToken()) {
mSaveKeyringParcel.addOrReplaceSubkeyChange( mSkpBuilder.addOrReplaceSubkeyChange(
SubkeyChange.createMoveToSecurityTokenChange(keyId)); SubkeyChange.createMoveToSecurityTokenChange(keyId));
break; break;
} else { } else {
mSaveKeyringParcel.removeSubkeyChange(change); mSkpBuilder.removeSubkeyChange(change);
} }
break; break;
} }
@@ -514,7 +514,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY: case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY:
Long expiry = (Long) message.getData().getSerializable( Long expiry = (Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY); EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
mSaveKeyringParcel.addOrReplaceSubkeyChange( mSkpBuilder.addOrReplaceSubkeyChange(
SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry)); SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry));
break; break;
} }
@@ -576,20 +576,20 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
} }
protected void returnKeyringParcel() { 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(); Notify.create(getActivity(), R.string.edit_key_error_add_identity, Notify.Style.ERROR).show();
return; 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(); Notify.create(getActivity(), R.string.edit_key_error_add_subkey, Notify.Style.ERROR).show();
return; return;
} }
// use first user id as primary String firstUserId = mSkpBuilder.getMutableAddUserIds().get(0);
mSaveKeyringParcel.mChangePrimaryUserId = mSaveKeyringParcel.mAddUserIds.get(0); mSkpBuilder.setChangePrimaryUserId(firstUserId);
Intent returnIntent = new Intent(); 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().setResult(Activity.RESULT_OK, returnIntent);
getActivity().finish(); getActivity().finish();
} }
@@ -610,7 +610,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
@Override @Override
public SaveKeyringParcel createOperationInput() { public SaveKeyringParcel createOperationInput() {
return mSaveKeyringParcel; return mSkpBuilder.build();
} }
@Override @Override

View File

@@ -82,7 +82,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
private long mMasterKeyId; private long mMasterKeyId;
private byte[] mFingerprint; private byte[] mFingerprint;
private boolean mHasSecret; private boolean mHasSecret;
private SaveKeyringParcel mEditModeSaveKeyringParcel; private SaveKeyringParcel.Builder mEditModeSkpBuilder;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
@@ -250,15 +250,15 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
@Override @Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) { public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mEditModeSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint); mEditModeSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
mSubkeysAddedAdapter = mSubkeysAddedAdapter = new SubkeysAddedAdapter(
new SubkeysAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddSubKeys, false); getActivity(), mEditModeSkpBuilder.getMutableAddSubKeys(), false);
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter); mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
mSubkeysAddedLayout.setVisibility(View.VISIBLE); mSubkeysAddedLayout.setVisibility(View.VISIBLE);
mSubkeyAddFabLayout.setDisplayedChild(1); mSubkeyAddFabLayout.setDisplayedChild(1);
mSubkeysAdapter.setEditMode(mEditModeSaveKeyringParcel); mSubkeysAdapter.setEditMode(mEditModeSkpBuilder);
getLoaderManager().restartLoader(LOADER_ID_SUBKEYS, null, ViewKeyAdvSubkeysFragment.this); getLoaderManager().restartLoader(LOADER_ID_SUBKEYS, null, ViewKeyAdvSubkeysFragment.this);
mode.setTitle(R.string.title_edit_subkeys); mode.setTitle(R.string.title_edit_subkeys);
@@ -280,7 +280,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
@Override @Override
public void onDestroyActionMode(ActionMode mode) { public void onDestroyActionMode(ActionMode mode) {
mEditModeSaveKeyringParcel = null; mEditModeSkpBuilder = null;
mSubkeysAdapter.setEditMode(null); mSubkeysAdapter.setEditMode(null);
mSubkeysAddedLayout.setVisibility(View.GONE); mSubkeysAddedLayout.setVisibility(View.GONE);
mSubkeyAddFabLayout.setDisplayedChild(0); mSubkeyAddFabLayout.setDisplayedChild(0);
@@ -323,10 +323,10 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
break; break;
case EditSubkeyDialogFragment.MESSAGE_REVOKE: case EditSubkeyDialogFragment.MESSAGE_REVOKE:
// toggle // toggle
if (mEditModeSaveKeyringParcel.mRevokeSubKeys.contains(keyId)) { if (mEditModeSkpBuilder.getMutableRevokeSubKeys().contains(keyId)) {
mEditModeSaveKeyringParcel.mRevokeSubKeys.remove(keyId); mEditModeSkpBuilder.removeRevokeSubkey(keyId);
} else { } else {
mEditModeSaveKeyringParcel.mRevokeSubKeys.add(keyId); mEditModeSkpBuilder.addRevokeSubkey(keyId);
} }
break; break;
case EditSubkeyDialogFragment.MESSAGE_STRIP: { case EditSubkeyDialogFragment.MESSAGE_STRIP: {
@@ -336,11 +336,11 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
break; break;
} }
SubkeyChange change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId); SubkeyChange change = mEditModeSkpBuilder.getSubkeyChange(keyId);
if (change == null || !change.getDummyStrip()) { if (change == null || !change.getDummyStrip()) {
mEditModeSaveKeyringParcel.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId)); mEditModeSkpBuilder.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId));
} else { } else {
mEditModeSaveKeyringParcel.removeSubkeyChange(change); mEditModeSkpBuilder.removeSubkeyChange(change);
} }
break; break;
} }
@@ -380,12 +380,12 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
break; break;
} }
SubkeyChange change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId); SubkeyChange change = mEditModeSkpBuilder.getSubkeyChange(keyId);
if (change == null || !change.getMoveKeyToSecurityToken()) { if (change == null || !change.getMoveKeyToSecurityToken()) {
mEditModeSaveKeyringParcel.addOrReplaceSubkeyChange( mEditModeSkpBuilder.addOrReplaceSubkeyChange(
SubkeyChange.createMoveToSecurityTokenChange(keyId)); SubkeyChange.createMoveToSecurityTokenChange(keyId));
} else { } else {
mEditModeSaveKeyringParcel.removeSubkeyChange(change); mEditModeSkpBuilder.removeSubkeyChange(change);
} }
break; break;
} }
@@ -419,7 +419,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY: case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY:
Long expiry = (Long) message.getData().getSerializable( Long expiry = (Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY); EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
mEditModeSaveKeyringParcel.addOrReplaceSubkeyChange( mEditModeSkpBuilder.addOrReplaceSubkeyChange(
SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry)); SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry));
break; break;
} }
@@ -447,7 +447,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
@Override @Override
public SaveKeyringParcel createOperationInput() { public SaveKeyringParcel createOperationInput() {
return mEditModeSaveKeyringParcel; return mEditModeSkpBuilder.build();
} }
@Override @Override

View File

@@ -79,7 +79,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
private long mMasterKeyId; private long mMasterKeyId;
private byte[] mFingerprint; private byte[] mFingerprint;
private boolean mHasSecret; private boolean mHasSecret;
private SaveKeyringParcel mEditModeSaveKeyringParcel; private SaveKeyringParcel.Builder mSkpBuilder;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { 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) { private void showOrEditUserIdInfo(final int position) {
if (mEditModeSaveKeyringParcel != null) { if (mSkpBuilder != null) {
editUserId(position); editUserId(position);
} else { } else {
showUserIdInfo(position); showUserIdInfo(position);
@@ -140,23 +140,23 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
switch (message.what) { switch (message.what) {
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID: case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
// toggle // toggle
if (mEditModeSaveKeyringParcel.mChangePrimaryUserId != null if (mSkpBuilder.getChangePrimaryUserId() != null
&& mEditModeSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { && mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mEditModeSaveKeyringParcel.mChangePrimaryUserId = null; mSkpBuilder.setChangePrimaryUserId(null);
} else { } else {
mEditModeSaveKeyringParcel.mChangePrimaryUserId = userId; mSkpBuilder.setChangePrimaryUserId(userId);
} }
break; break;
case EditUserIdDialogFragment.MESSAGE_REVOKE: case EditUserIdDialogFragment.MESSAGE_REVOKE:
// toggle // toggle
if (mEditModeSaveKeyringParcel.mRevokeUserIds.contains(userId)) { if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
mEditModeSaveKeyringParcel.mRevokeUserIds.remove(userId); mSkpBuilder.removeRevokeUserId(userId);
} else { } else {
mEditModeSaveKeyringParcel.mRevokeUserIds.add(userId); mSkpBuilder.addRevokeUserId(userId);
// not possible to revoke and change to primary user id // not possible to revoke and change to primary user id
if (mEditModeSaveKeyringParcel.mChangePrimaryUserId != null if (mSkpBuilder.getChangePrimaryUserId() != null
&& mEditModeSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) { && mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mEditModeSaveKeyringParcel.mChangePrimaryUserId = null; mSkpBuilder.setChangePrimaryUserId(null);
} }
} }
break; break;
@@ -342,15 +342,15 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
@Override @Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) { public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mEditModeSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint); mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
mUserIdsAddedAdapter = mUserIdsAddedAdapter =
new UserIdsAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddUserIds, false); new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), false);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
mUserIdsAddedLayout.setVisibility(View.VISIBLE); mUserIdsAddedLayout.setVisibility(View.VISIBLE);
mUserIdAddFabLayout.setDisplayedChild(1); mUserIdAddFabLayout.setDisplayedChild(1);
mUserIdsAdapter.setEditMode(mEditModeSaveKeyringParcel); mUserIdsAdapter.setEditMode(mSkpBuilder);
getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this); getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this);
mode.setTitle(R.string.title_edit_identities); mode.setTitle(R.string.title_edit_identities);
@@ -372,7 +372,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
@Override @Override
public void onDestroyActionMode(ActionMode mode) { public void onDestroyActionMode(ActionMode mode) {
mEditModeSaveKeyringParcel = null; mSkpBuilder = null;
mUserIdsAdapter.setEditMode(null); mUserIdsAdapter.setEditMode(null);
mUserIdsAddedLayout.setVisibility(View.GONE); mUserIdsAddedLayout.setVisibility(View.GONE);
mUserIdAddFabLayout.setDisplayedChild(0); mUserIdAddFabLayout.setDisplayedChild(0);
@@ -387,7 +387,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
@Override @Override
public SaveKeyringParcel createOperationInput() { public SaveKeyringParcel createOperationInput() {
return mEditModeSaveKeyringParcel; return mSkpBuilder.build();
} }
@Override @Override

View File

@@ -17,6 +17,11 @@
package org.sufficientlysecure.keychain.ui.adapter; 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.Context;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.database.Cursor; 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.service.SaveKeyringParcel.SubkeyChange;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class SubkeysAdapter extends CursorAdapter { public class SubkeysAdapter extends CursorAdapter {
private LayoutInflater mInflater; private LayoutInflater mInflater;
private SaveKeyringParcel mSaveKeyringParcel; private SaveKeyringParcel.Builder mSkpBuilder;
private boolean mHasAnySecret; private boolean mHasAnySecret;
private ColorStateList mDefaultTextColor; private ColorStateList mDefaultTextColor;
@@ -177,10 +178,7 @@ public class SubkeysAdapter extends CursorAdapter {
cursor.getString(INDEX_KEY_CURVE_OID) cursor.getString(INDEX_KEY_CURVE_OID)
)); ));
SubkeyChange change = mSaveKeyringParcel != null SubkeyChange change = mSkpBuilder != null ? mSkpBuilder.getSubkeyChange(keyId) : null;
? mSaveKeyringParcel.getSubkeyChange(keyId)
: null;
if (change != null && (change.getDummyStrip() || change.getMoveKeyToSecurityToken())) { if (change != null && (change.getDummyStrip() || change.getMoveKeyToSecurityToken())) {
if (change.getDummyStrip()) { if (change.getDummyStrip()) {
algorithmStr.append(", "); algorithmStr.append(", ");
@@ -242,8 +240,8 @@ public class SubkeysAdapter extends CursorAdapter {
} }
// for edit key // for edit key
if (mSaveKeyringParcel != null) { if (mSkpBuilder != null) {
boolean revokeThisSubkey = (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId)); boolean revokeThisSubkey = (mSkpBuilder.getMutableRevokeSubKeys().contains(keyId));
if (revokeThisSubkey) { if (revokeThisSubkey) {
if (!isRevoked) { if (!isRevoked) {
@@ -251,7 +249,7 @@ public class SubkeysAdapter extends CursorAdapter {
} }
} }
SaveKeyringParcel.SubkeyChange subkeyChange = mSaveKeyringParcel.getSubkeyChange(keyId); SaveKeyringParcel.SubkeyChange subkeyChange = mSkpBuilder.getSubkeyChange(keyId);
if (subkeyChange != null) { if (subkeyChange != null) {
if (subkeyChange.getExpiry() == null || subkeyChange.getExpiry() == 0L) { if (subkeyChange.getExpiry() == null || subkeyChange.getExpiry() == 0L) {
expiryDate = null; expiryDate = null;
@@ -345,7 +343,7 @@ public class SubkeysAdapter extends CursorAdapter {
// Disable selection of items, http://stackoverflow.com/a/4075045 // Disable selection of items, http://stackoverflow.com/a/4075045
@Override @Override
public boolean areAllItemsEnabled() { public boolean areAllItemsEnabled() {
if (mSaveKeyringParcel == null) { if (mSkpBuilder == null) {
return false; return false;
} else { } else {
return super.areAllItemsEnabled(); return super.areAllItemsEnabled();
@@ -355,7 +353,7 @@ public class SubkeysAdapter extends CursorAdapter {
// Disable selection of items, http://stackoverflow.com/a/4075045 // Disable selection of items, http://stackoverflow.com/a/4075045
@Override @Override
public boolean isEnabled(int position) { public boolean isEnabled(int position) {
if (mSaveKeyringParcel == null) { if (mSkpBuilder == null) {
return false; return false;
} else { } else {
return super.isEnabled(position); return super.isEnabled(position);
@@ -370,10 +368,10 @@ public class SubkeysAdapter extends CursorAdapter {
* *
* @see SaveKeyringParcel * @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) { public void setEditMode(@Nullable SaveKeyringParcel.Builder builder) {
mSaveKeyringParcel = saveKeyringParcel; mSkpBuilder = builder;
} }
} }

View File

@@ -32,9 +32,7 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.ViewAnimator; import android.widget.ViewAnimator;
import org.openintents.openpgp.util.OpenPgpUtils;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
@@ -43,20 +41,18 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
public class UserIdsAdapter extends UserAttributesAdapter { public class UserIdsAdapter extends UserAttributesAdapter {
protected LayoutInflater mInflater; protected LayoutInflater mInflater;
private SaveKeyringParcel mSaveKeyringParcel; private SaveKeyringParcel.Builder mSkpBuilder;
private boolean mShowStatusImages; private boolean mShowStatusImages;
public UserIdsAdapter(Context context, Cursor c, int flags, public UserIdsAdapter(Context context, Cursor c, int flags, boolean showStatusImages) {
boolean showStatusImages, SaveKeyringParcel saveKeyringParcel) {
super(context, c, flags); super(context, c, flags);
mInflater = LayoutInflater.from(context); mInflater = LayoutInflater.from(context);
mSaveKeyringParcel = saveKeyringParcel;
mShowStatusImages = showStatusImages; mShowStatusImages = showStatusImages;
} }
public UserIdsAdapter(Context context, Cursor c, int flags) { public UserIdsAdapter(Context context, Cursor c, int flags) {
this(context, c, flags, true, null); this(context, c, flags, true);
} }
@Override @Override
@@ -96,11 +92,11 @@ public class UserIdsAdapter extends UserAttributesAdapter {
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
// for edit key // for edit key
if (mSaveKeyringParcel != null) { if (mSkpBuilder != null) {
boolean changeAnyPrimaryUserId = (mSaveKeyringParcel.mChangePrimaryUserId != null); String changePrimaryUserId = mSkpBuilder.getChangePrimaryUserId();
boolean changeThisPrimaryUserId = (mSaveKeyringParcel.mChangePrimaryUserId != null boolean changeAnyPrimaryUserId = (changePrimaryUserId != null);
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)); boolean changeThisPrimaryUserId = (changeAnyPrimaryUserId && changePrimaryUserId.equals(userId));
boolean revokeThisUserId = (mSaveKeyringParcel.mRevokeUserIds.contains(userId)); boolean revokeThisUserId = (mSkpBuilder.getMutableRevokeUserIds().contains(userId));
// only if primary user id will be changed // only if primary user id will be changed
// (this is not triggered if the user id is currently the primary one) // (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); String userId = mCursor.getString(INDEX_USER_ID);
boolean isRevokedPending = false; boolean isRevokedPending = false;
if (mSaveKeyringParcel != null) { if (mSkpBuilder != null) {
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) { if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
isRevokedPending = true; 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. * @param saveKeyringParcel The parcel to get info from, or null to leave edit mode.
*/ */
public void setEditMode(@Nullable SaveKeyringParcel saveKeyringParcel) { public void setEditMode(@Nullable SaveKeyringParcel.Builder saveKeyringParcel) {
mSaveKeyringParcel = saveKeyringParcel; mSkpBuilder = saveKeyringParcel;
} }
@Override @Override

View File

@@ -143,7 +143,7 @@ public class ViewKeyFragment extends LoaderFragment implements LoaderManager.Loa
mIsSecret = getArguments().getBoolean(ARG_IS_SECRET); mIsSecret = getArguments().getBoolean(ARG_IS_SECRET);
// load user ids after we know if it's a secret key // 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); mUserIds.setAdapter(mUserIdsAdapter);
// initialize loaders, which will take care of auto-refresh on change // initialize loaders, which will take care of auto-refresh on change

View File

@@ -210,15 +210,11 @@ public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragmen
@Nullable @Nullable
@Override @Override
public Parcelable createOperationInput() { public Parcelable createOperationInput() {
SaveKeyringParcel skp = SaveKeyringParcel.Builder builder=
new SaveKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint); SaveKeyringParcel.buildChangeKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint);
WrappedUserAttribute ua = LinkedAttribute.fromResource(mVerifiedResource).toUserAttribute();
WrappedUserAttribute ua = builder.addUserAttribute(ua);
LinkedAttribute.fromResource(mVerifiedResource).toUserAttribute(); return builder.build();
skp.mAddUserAttribute.add(ua);
return skp;
} }
@Override @Override

View File

@@ -96,7 +96,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
byte[] mFingerprint; byte[] mFingerprint;
long mMasterKeyId; long mMasterKeyId;
private SaveKeyringParcel mSaveKeyringParcel; private SaveKeyringParcel.Builder mSkpBuilder;
private TextView mLinkedIdTitle, mLinkedIdComment; private TextView mLinkedIdTitle, mLinkedIdComment;
private boolean mFinishOnStop; private boolean mFinishOnStop;
@@ -405,13 +405,10 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
new Handler().postDelayed(new Runnable() { new Handler().postDelayed(new Runnable() {
@Override @Override
public void run() { public void run() {
WrappedUserAttribute ua = LinkedAttribute.fromResource(resource).toUserAttribute(); WrappedUserAttribute ua = LinkedAttribute.fromResource(resource).toUserAttribute();
mSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint); mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
mSaveKeyringParcel.mAddUserAttribute.add(ua); mSkpBuilder.addUserAttribute(ua);
cryptoOperation(); cryptoOperation();
} }
}, 250); }, 250);
@@ -421,7 +418,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
@Override @Override
public SaveKeyringParcel createOperationInput() { public SaveKeyringParcel createOperationInput() {
// if this is null, the cryptoOperation silently aborts - which is what we want in that case // if this is null, the cryptoOperation silently aborts - which is what we want in that case
return mSaveKeyringParcel; return mSkpBuilder.build();
} }
@Override @Override

View File

@@ -95,17 +95,17 @@ public class BackupOperationTest {
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L));
parcel.mAddUserIds.add("snips"); builder.addUserId("snips");
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(mKeyPhrase1)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(mKeyPhrase1));
PgpEditKeyResult result = op.createSecretKeyRing(parcel); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
assertTrue("initial test key creation must succeed", result.success()); assertTrue("initial test key creation must succeed", result.success());
Assert.assertNotNull("initial test key creation must succeed", result.getRing()); Assert.assertNotNull("initial test key creation must succeed", result.getRing());
@@ -113,17 +113,17 @@ public class BackupOperationTest {
} }
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L));
parcel.mAddUserIds.add("snails"); builder.addUserId("snails");
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase("1234"))); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase("1234")));
PgpEditKeyResult result = op.createSecretKeyRing(parcel); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
assertTrue("initial test key creation must succeed", result.success()); assertTrue("initial test key creation must succeed", result.success());
Assert.assertNotNull("initial test key creation must succeed", result.getRing()); Assert.assertNotNull("initial test key creation must succeed", result.getRing());

View File

@@ -73,17 +73,17 @@ public class CertifyOperationTest {
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L));
parcel.mAddUserIds.add("derp"); builder.addUserId("derp");
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(mKeyPhrase1)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(mKeyPhrase1));
PgpEditKeyResult result = op.createSecretKeyRing(parcel); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
Assert.assertTrue("initial test key creation must succeed", result.success()); Assert.assertTrue("initial test key creation must succeed", result.success());
Assert.assertNotNull("initial test key creation must succeed", result.getRing()); Assert.assertNotNull("initial test key creation must succeed", result.getRing());
@@ -91,23 +91,22 @@ public class CertifyOperationTest {
} }
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L));
parcel.mAddUserIds.add("ditz"); builder.addUserId("ditz");
byte[] uatdata = new byte[random.nextInt(150)+10]; byte[] uatdata = new byte[random.nextInt(150)+10];
random.nextBytes(uatdata); random.nextBytes(uatdata);
parcel.mAddUserAttribute.add( builder.addUserAttribute(WrappedUserAttribute.fromSubpacket(random.nextInt(100)+1, uatdata));
WrappedUserAttribute.fromSubpacket(random.nextInt(100)+1, uatdata));
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(mKeyPhrase2)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(mKeyPhrase2));
PgpEditKeyResult result = op.createSecretKeyRing(parcel); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
Assert.assertTrue("initial test key creation must succeed", result.success()); Assert.assertTrue("initial test key creation must succeed", result.success());
Assert.assertNotNull("initial test key creation must succeed", result.getRing()); Assert.assertNotNull("initial test key creation must succeed", result.getRing());

View File

@@ -69,17 +69,17 @@ public class PromoteKeyOperationTest {
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L));
parcel.mAddUserIds.add("derp"); builder.addUserId("derp");
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(mKeyPhrase1)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(mKeyPhrase1));
PgpEditKeyResult result = op.createSecretKeyRing(parcel); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
Assert.assertTrue("initial test key creation must succeed", result.success()); Assert.assertTrue("initial test key creation must succeed", result.success());
Assert.assertNotNull("initial test key creation must succeed", result.getRing()); Assert.assertNotNull("initial test key creation must succeed", result.getRing());

View File

@@ -621,10 +621,10 @@ public class PgpEncryptDecryptTest {
{ // strip first encrypted subkey, decryption should skip it { // strip first encrypted subkey, decryption should skip it
SaveKeyringParcel parcel = SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildChangeKeyringParcel(
new SaveKeyringParcel(mStaticRing1.getMasterKeyId(), mStaticRing1.getFingerprint()); mStaticRing1.getMasterKeyId(), mStaticRing1.getFingerprint());
parcel.mChangeSubKeys.add(SubkeyChange.createStripChange(encKeyId1)); builder.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(encKeyId1));
UncachedKeyRing modified = PgpKeyOperationTest.applyModificationWithChecks(parcel, mStaticRing1, UncachedKeyRing modified = PgpKeyOperationTest.applyModificationWithChecks(builder.build(), mStaticRing1,
new ArrayList<RawPacket>(), new ArrayList<RawPacket>(), new ArrayList<RawPacket>(), new ArrayList<RawPacket>(),
CryptoInputParcel.createCryptoInputParcel(new Date(), mKeyPhrase1)); CryptoInputParcel.createCryptoInputParcel(new Date(), mKeyPhrase1));
@@ -644,10 +644,10 @@ public class PgpEncryptDecryptTest {
{ // change flags of second encrypted subkey, decryption should skip it { // change flags of second encrypted subkey, decryption should skip it
SaveKeyringParcel parcel = SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildChangeKeyringParcel(
new SaveKeyringParcel(mStaticRing1.getMasterKeyId(), mStaticRing1.getFingerprint()); mStaticRing1.getMasterKeyId(), mStaticRing1.getFingerprint());
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(encKeyId1, KeyFlags.CERTIFY_OTHER, null)); builder.addOrReplaceSubkeyChange(SubkeyChange.createFlagsOrExpiryChange(encKeyId1, KeyFlags.CERTIFY_OTHER, null));
UncachedKeyRing modified = PgpKeyOperationTest.applyModificationWithChecks(parcel, mStaticRing1, UncachedKeyRing modified = PgpKeyOperationTest.applyModificationWithChecks(builder.build(), mStaticRing1,
new ArrayList<RawPacket>(), new ArrayList<RawPacket>(), new ArrayList<RawPacket>(), new ArrayList<RawPacket>(),
CryptoInputParcel.createCryptoInputParcel(new Date(), mKeyPhrase1)); CryptoInputParcel.createCryptoInputParcel(new Date(), mKeyPhrase1));
@@ -673,9 +673,10 @@ public class PgpEncryptDecryptTest {
String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true); String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true);
{ // revoke first encryption subkey of keyring in database { // revoke first encryption subkey of keyring in database
SaveKeyringParcel parcel = new SaveKeyringParcel(mStaticRing1.getMasterKeyId(), mStaticRing1.getFingerprint()); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildChangeKeyringParcel(
parcel.mRevokeSubKeys.add(KeyringTestingHelper.getSubkeyId(mStaticRing1, 2)); mStaticRing1.getMasterKeyId(), mStaticRing1.getFingerprint());
UncachedKeyRing modified = PgpKeyOperationTest.applyModificationWithChecks(parcel, mStaticRing1, builder.addRevokeSubkey(KeyringTestingHelper.getSubkeyId(mStaticRing1, 2));
UncachedKeyRing modified = PgpKeyOperationTest.applyModificationWithChecks(builder.build(), mStaticRing1,
new ArrayList<RawPacket>(), new ArrayList<RawPacket>(), new ArrayList<RawPacket>(), new ArrayList<RawPacket>(),
CryptoInputParcel.createCryptoInputParcel(new Date(), mKeyPhrase1)); CryptoInputParcel.createCryptoInputParcel(new Date(), mKeyPhrase1));

View File

@@ -18,8 +18,20 @@
package org.sufficientlysecure.keychain.pgp; package org.sufficientlysecure.keychain.pgp;
import junit.framework.AssertionFailedError;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import junit.framework.AssertionFailedError;
import org.bouncycastle.bcpg.BCPGInputStream; import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.Packet; import org.bouncycastle.bcpg.Packet;
import org.bouncycastle.bcpg.PacketTags; import org.bouncycastle.bcpg.PacketTags;
@@ -58,16 +70,18 @@ import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler; import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.TestingUtils; import org.sufficientlysecure.keychain.util.TestingUtils;
import java.io.ByteArrayInputStream; import static org.bouncycastle.bcpg.sig.KeyFlags.CERTIFY_OTHER;
import java.io.IOException; import static org.bouncycastle.bcpg.sig.KeyFlags.SIGN_DATA;
import java.nio.ByteBuffer; import static org.sufficientlysecure.keychain.operations.results.OperationResult.LogType.MSG_MF_ERROR_FINGERPRINT;
import java.security.Security; import static org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm.ECDSA;
import java.util.ArrayList; import static org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm.RSA;
import java.util.Date; import static org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve.NIST_P256;
import java.util.HashSet; import static org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd.createSubkeyAdd;
import java.util.Iterator; import static org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange.createFlagsOrExpiryChange;
import java.util.List; import static org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange.createRecertifyChange;
import java.util.Random; import static org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange.createStripChange;
import static org.sufficientlysecure.keychain.service.SaveKeyringParcel.buildChangeKeyringParcel;
@RunWith(KeychainTestRunner.class) @RunWith(KeychainTestRunner.class)
public class PgpKeyOperationTest { public class PgpKeyOperationTest {
@@ -77,7 +91,7 @@ public class PgpKeyOperationTest {
UncachedKeyRing ring; UncachedKeyRing ring;
PgpKeyOperation op; PgpKeyOperation op;
SaveKeyringParcel parcel; SaveKeyringParcel.Builder builder;
ArrayList<RawPacket> onlyA = new ArrayList<>(); ArrayList<RawPacket> onlyA = new ArrayList<>();
ArrayList<RawPacket> onlyB = new ArrayList<>(); ArrayList<RawPacket> onlyB = new ArrayList<>();
@@ -88,28 +102,28 @@ public class PgpKeyOperationTest {
Security.insertProviderAt(new BouncyCastleProvider(), 1); Security.insertProviderAt(new BouncyCastleProvider(), 1);
ShadowLog.stream = System.out; ShadowLog.stream = System.out;
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L));
parcel.mAddUserIds.add("twi"); builder.addUserId("twi");
parcel.mAddUserIds.add("pink"); builder.addUserId("pink");
{ {
int type = 42; int type = 42;
byte[] data = new byte[] { 0, 1, 2, 3, 4 }; byte[] data = new byte[] { 0, 1, 2, 3, 4 };
WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data); WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data);
parcel.mAddUserAttribute.add(uat); builder.addUserAttribute(uat);
} }
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase));
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
PgpEditKeyResult result = op.createSecretKeyRing(parcel); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
Assert.assertTrue("initial test key creation must succeed", result.success()); Assert.assertTrue("initial test key creation must succeed", result.success());
Assert.assertNotNull("initial test key creation must succeed", result.getRing()); Assert.assertNotNull("initial test key creation must succeed", result.getRing());
@@ -123,7 +137,8 @@ public class PgpKeyOperationTest {
} }
@Before public void setUp() throws Exception { @Before
public void setUp() throws Exception {
// show Log.x messages in system.out // show Log.x messages in system.out
ShadowLog.stream = System.out; ShadowLog.stream = System.out;
ring = staticRing; ring = staticRing;
@@ -131,76 +146,76 @@ public class PgpKeyOperationTest {
// setting up some parameters just to reduce code duplication // setting up some parameters just to reduce code duplication
op = new PgpKeyOperation(new ProgressScaler(null, 0, 100, 100)); op = new PgpKeyOperation(new ProgressScaler(null, 0, 100, 100));
// set this up, gonna need it more than once resetBuilder();
parcel = new SaveKeyringParcel(); }
parcel.mMasterKeyId = ring.getMasterKeyId();
parcel.mFingerprint = ring.getFingerprint();
private void resetBuilder() {
builder = SaveKeyringParcel.buildChangeKeyringParcel(ring.getMasterKeyId(), ring.getFingerprint());
} }
@Test @Test
public void createSecretKeyRingTests() { public void createSecretKeyRingTests() {
{ {
parcel.reset(); resetBuilder();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.RSA, new Random().nextInt(256)+255, null, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.RSA, new Random().nextInt(256)+255, null, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddUserIds.add("shy"); builder.addUserId("shy");
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase));
assertFailure("creating ring with < 2048 bit keysize should fail", parcel, assertFailure("creating ring with < 2048 bit keysize should fail", builder.build(),
LogType.MSG_CR_ERROR_KEYSIZE_2048); LogType.MSG_CR_ERROR_KEYSIZE_2048);
} }
{ {
parcel.reset(); resetBuilder();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ELGAMAL, 2048, null, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ELGAMAL, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddUserIds.add("shy"); builder.addUserId("shy");
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase));
assertFailure("creating ring with ElGamal master key should fail", parcel, assertFailure("creating ring with ElGamal master key should fail", builder.build(),
LogType.MSG_CR_ERROR_FLAGS_ELGAMAL); LogType.MSG_CR_ERROR_FLAGS_ELGAMAL);
} }
{ {
parcel.reset(); resetBuilder();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, null)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, null));
parcel.mAddUserIds.add("lotus"); builder.addUserId("lotus");
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase));
assertFailure("creating master key with null expiry should fail", parcel, assertFailure("creating master key with null expiry should fail", builder.build(),
LogType.MSG_CR_ERROR_NULL_EXPIRY); LogType.MSG_CR_ERROR_NULL_EXPIRY);
} }
{ {
parcel.reset(); resetBuilder();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddUserIds.add("shy"); builder.addUserId("shy");
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase));
assertFailure("creating ring with non-certifying master key should fail", parcel, assertFailure("creating ring with non-certifying master key should fail", builder.build(),
LogType.MSG_CR_ERROR_NO_CERTIFY); LogType.MSG_CR_ERROR_NO_CERTIFY);
} }
{ {
parcel.reset(); resetBuilder();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase));
assertFailure("creating ring without user ids should fail", parcel, assertFailure("creating ring without user ids should fail", builder.build(),
LogType.MSG_CR_ERROR_NO_USER_ID); LogType.MSG_CR_ERROR_NO_USER_ID);
} }
{ {
parcel.reset(); resetBuilder();
parcel.mAddUserIds.add("shy"); builder.addUserId("shy");
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase));
assertFailure("creating ring with no master key should fail", parcel, assertFailure("creating ring with no master key should fail", builder.build(),
LogType.MSG_CR_ERROR_NO_MASTER); LogType.MSG_CR_ERROR_NO_MASTER);
} }
@@ -210,11 +225,11 @@ public class PgpKeyOperationTest {
// this is a special case since the flags are in user id certificates rather than // this is a special case since the flags are in user id certificates rather than
// subkey binding certificates // subkey binding certificates
public void testMasterFlags() throws Exception { public void testMasterFlags() throws Exception {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, 0L));
parcel.mAddUserIds.add("luna"); builder.addUserId("luna");
ring = assertCreateSuccess("creating ring with master key flags must succeed", parcel); ring = assertCreateSuccess("creating ring with master key flags must succeed", builder.build());
Assert.assertEquals("the keyring should contain only the master key", Assert.assertEquals("the keyring should contain only the master key",
1, KeyringTestingHelper.itToList(ring.getPublicKeys()).size()); 1, KeyringTestingHelper.itToList(ring.getPublicKeys()).size());
@@ -280,43 +295,27 @@ public class PgpKeyOperationTest {
public void testBadKeyModification() throws Exception { public void testBadKeyModification() throws Exception {
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildChangeKeyringParcel(
// off by one ring.getMasterKeyId() -1, ring.getFingerprint());
parcel.mMasterKeyId = ring.getMasterKeyId() -1;
parcel.mFingerprint = ring.getFingerprint();
assertModifyFailure("keyring modification with bad master key id should fail", assertModifyFailure("keyring modification with bad master key id should fail",
ring, parcel, LogType.MSG_MF_ERROR_KEYID); ring, builder.build(), LogType.MSG_MF_ERROR_KEYID);
} }
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); byte[] fingerprint = Arrays.copyOf(ring.getFingerprint(), ring.getFingerprint().length);
// off by one fingerprint[5] += 1;
parcel.mMasterKeyId = null;
parcel.mFingerprint = ring.getFingerprint();
assertModifyFailure("keyring modification with null master key id should fail", SaveKeyringParcel.Builder builder = buildChangeKeyringParcel(ring.getMasterKeyId(), fingerprint);
ring, parcel, LogType.MSG_MF_ERROR_KEYID);
}
{
SaveKeyringParcel parcel = new SaveKeyringParcel();
parcel.mMasterKeyId = ring.getMasterKeyId();
parcel.mFingerprint = ring.getFingerprint();
// some byte, off by one
parcel.mFingerprint[5] += 1;
assertModifyFailure("keyring modification with bad fingerprint should fail", assertModifyFailure("keyring modification with bad fingerprint should fail",
ring, parcel, LogType.MSG_MF_ERROR_FINGERPRINT); ring, builder.build(), MSG_MF_ERROR_FINGERPRINT);
} }
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = buildChangeKeyringParcel(ring.getMasterKeyId(), null);
parcel.mMasterKeyId = ring.getMasterKeyId();
parcel.mFingerprint = null;
assertModifyFailure("keyring modification with null fingerprint should fail", assertModifyFailure("keyring modification with null fingerprint should fail",
ring, parcel, LogType.MSG_MF_ERROR_FINGERPRINT); ring, builder.build(), MSG_MF_ERROR_FINGERPRINT);
} }
{ {
@@ -324,16 +323,16 @@ public class PgpKeyOperationTest {
if (badphrase.equals(passphrase)) { if (badphrase.equals(passphrase)) {
badphrase = new Passphrase("a"); badphrase = new Passphrase("a");
} }
parcel.mAddUserIds.add("allure"); builder.addUserId("allure");
assertModifyFailure("keyring modification with bad passphrase should fail", assertModifyFailure("keyring modification with bad passphrase should fail",
ring, parcel, CryptoInputParcel.createCryptoInputParcel(badphrase), LogType.MSG_MF_UNLOCK_ERROR); ring, builder.build(), CryptoInputParcel.createCryptoInputParcel(badphrase), LogType.MSG_MF_UNLOCK_ERROR);
} }
{ {
parcel.reset(); resetBuilder();
assertModifyFailure("no-op should fail", assertModifyFailure("no-op should fail",
ring, parcel, cryptoInput, LogType.MSG_MF_ERROR_NOOP); ring, builder.build(), cryptoInput, LogType.MSG_MF_ERROR_NOOP);
} }
} }
@@ -343,10 +342,10 @@ public class PgpKeyOperationTest {
long expiry = new Date().getTime() / 1000 + 159; long expiry = new Date().getTime() / 1000 + 159;
int flags = KeyFlags.SIGN_DATA; int flags = KeyFlags.SIGN_DATA;
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, flags, expiry)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, flags, expiry));
UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB); UncachedKeyRing modified = applyModificationWithChecks(builder.build(), ring, onlyA, onlyB);
Assert.assertEquals("no extra packets in original", 0, onlyA.size()); Assert.assertEquals("no extra packets in original", 0, onlyA.size());
Assert.assertEquals("exactly two extra packets in modified", 2, onlyB.size()); Assert.assertEquals("exactly two extra packets in modified", 2, onlyB.size());
@@ -381,26 +380,27 @@ public class PgpKeyOperationTest {
flags, (long) newKey.getKeyUsage()); flags, (long) newKey.getKeyUsage());
{ // bad keysize should fail { // bad keysize should fail
parcel.reset(); resetBuilder();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(createSubkeyAdd(
Algorithm.RSA, new Random().nextInt(512), null, KeyFlags.SIGN_DATA, 0L)); RSA, new Random().nextInt(512), null, SIGN_DATA, 0L));
assertModifyFailure("creating a subkey with keysize < 2048 should fail", ring, parcel, assertModifyFailure("creating a subkey with keysize < 2048 should fail", ring, builder.build(),
LogType.MSG_CR_ERROR_KEYSIZE_2048); LogType.MSG_CR_ERROR_KEYSIZE_2048);
} }
{ // null expiry should fail { // null expiry should fail
parcel.reset(); resetBuilder();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, null)); ECDSA, 0, NIST_P256, SIGN_DATA, null));
assertModifyFailure("creating master key with null expiry should fail", ring, parcel, assertModifyFailure("creating master key with null expiry should fail", ring, builder.build(),
LogType.MSG_MF_ERROR_NULL_EXPIRY); LogType.MSG_MF_ERROR_NULL_EXPIRY);
} }
{ // a past expiry should fail { // a past expiry should fail
parcel.reset(); resetBuilder();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, new Date().getTime()/1000-10)); ECDSA, 0, NIST_P256, SIGN_DATA,
assertModifyFailure("creating subkey with past expiry date should fail", ring, parcel, new Date().getTime() / 1000 - 10));
assertModifyFailure("creating subkey with past expiry date should fail", ring, builder.build(),
LogType.MSG_MF_ERROR_PAST_EXPIRY); LogType.MSG_MF_ERROR_PAST_EXPIRY);
} }
@@ -414,8 +414,8 @@ public class PgpKeyOperationTest {
UncachedKeyRing modified = ring; UncachedKeyRing modified = ring;
{ {
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, null, expiry));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertEquals("one extra packet in original", 1, onlyA.size()); Assert.assertEquals("one extra packet in original", 1, onlyA.size());
Assert.assertEquals("one extra packet in modified", 1, onlyB.size()); Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
@@ -441,8 +441,8 @@ public class PgpKeyOperationTest {
{ // change expiry { // change expiry
expiry += 60*60*24; expiry += 60*60*24;
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, null, expiry));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertNotNull("modified key must have an expiry date", Assert.assertNotNull("modified key must have an expiry date",
modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting()); modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
@@ -454,9 +454,9 @@ public class PgpKeyOperationTest {
{ {
int flags = KeyFlags.SIGN_DATA | KeyFlags.ENCRYPT_COMMS; int flags = KeyFlags.SIGN_DATA | KeyFlags.ENCRYPT_COMMS;
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, flags, null)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, flags, null));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertEquals("old packet must be signature", Assert.assertEquals("old packet must be signature",
PacketTags.SIGNATURE, onlyA.get(0).tag); PacketTags.SIGNATURE, onlyA.get(0).tag);
@@ -477,9 +477,9 @@ public class PgpKeyOperationTest {
} }
{ // expiry of 0 should be "no expiry" { // expiry of 0 should be "no expiry"
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, null, 0L)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, null, 0L));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertEquals("old packet must be signature", Assert.assertEquals("old packet must be signature",
PacketTags.SIGNATURE, onlyA.get(0).tag); PacketTags.SIGNATURE, onlyA.get(0).tag);
@@ -495,18 +495,18 @@ public class PgpKeyOperationTest {
} }
{ // a past expiry should fail { // a past expiry should fail
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, null, new Date().getTime()/1000-10)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, null, new Date().getTime() / 1000 - 10));
assertModifyFailure("setting subkey expiry to a past date should fail", ring, parcel, assertModifyFailure("setting subkey expiry to a past date should fail", ring, builder.build(),
LogType.MSG_MF_ERROR_PAST_EXPIRY); LogType.MSG_MF_ERROR_PAST_EXPIRY);
} }
{ // modifying nonexistent subkey should fail { // modifying nonexistent subkey should fail
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(123, null, null)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(123, null, null));
assertModifyFailure("modifying non-existent subkey should fail", ring, parcel, assertModifyFailure("modifying non-existent subkey should fail", ring, builder.build(),
LogType.MSG_MF_ERROR_SUBKEY_MISSING); LogType.MSG_MF_ERROR_SUBKEY_MISSING);
} }
@@ -521,15 +521,15 @@ public class PgpKeyOperationTest {
UncachedKeyRing modified = ring; UncachedKeyRing modified = ring;
// to make this check less trivial, we add a user id, change the primary one and revoke one // to make this check less trivial, we add a user id, change the primary one and revoke one
parcel.mAddUserIds.add("aloe"); builder.addUserId("aloe");
parcel.mChangePrimaryUserId = "aloe"; builder.setChangePrimaryUserId("aloe");
parcel.mRevokeUserIds.add("pink"); builder.addRevokeUserId("pink");
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
{ {
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, null, expiry));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
// this implies that only the two non-revoked signatures were changed! // this implies that only the two non-revoked signatures were changed!
Assert.assertEquals("two extra packets in original", 2, onlyA.size()); Assert.assertEquals("two extra packets in original", 2, onlyA.size());
@@ -555,8 +555,8 @@ public class PgpKeyOperationTest {
{ // change expiry { // change expiry
expiry += 60*60*24; expiry += 60*60*24;
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, null, expiry));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertNotNull("modified key must have an expiry date", Assert.assertNotNull("modified key must have an expiry date",
modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting()); modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
@@ -574,9 +574,9 @@ public class PgpKeyOperationTest {
{ {
int flags = KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA; int flags = KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA;
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, flags, null)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, flags, null));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertEquals("modified key must have expected flags", Assert.assertEquals("modified key must have expected flags",
flags, (long) modified.getPublicKey(keyId).getKeyUsage()); flags, (long) modified.getPublicKey(keyId).getKeyUsage());
@@ -590,13 +590,13 @@ public class PgpKeyOperationTest {
// even if there is a non-expiring user id while all others are revoked, it doesn't count! // even if there is a non-expiring user id while all others are revoked, it doesn't count!
// for this purpose we revoke one while they still have expiry times // for this purpose we revoke one while they still have expiry times
parcel.reset(); resetBuilder();
parcel.mRevokeUserIds.add("aloe"); builder.addRevokeUserId("aloe");
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, null, 0L)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, null, 0L));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
// for this check, it is relevant that we DON'T use the unsafe one! // for this check, it is relevant that we DON'T use the unsafe one!
Assert.assertNull("key must not expire anymore", Assert.assertNull("key must not expire anymore",
@@ -607,28 +607,28 @@ public class PgpKeyOperationTest {
} }
{ // if we revoke everything, nothing is left to properly sign... { // if we revoke everything, nothing is left to properly sign...
parcel.reset(); resetBuilder();
parcel.mRevokeUserIds.add("twi"); builder.addRevokeUserId("twi");
parcel.mRevokeUserIds.add("pink"); builder.addRevokeUserId("pink");
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, KeyFlags.CERTIFY_OTHER, null)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, CERTIFY_OTHER, null));
assertModifyFailure("master key modification with all user ids revoked should fail", ring, parcel, assertModifyFailure("master key modification with all user ids revoked should fail", ring, builder.build(),
LogType.MSG_MF_ERROR_MASTER_NONE); LogType.MSG_MF_ERROR_MASTER_NONE);
} }
{ // any flag not including CERTIFY_OTHER should fail { // any flag not including CERTIFY_OTHER should fail
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, KeyFlags.SIGN_DATA, null)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, SIGN_DATA, null));
assertModifyFailure("setting master key flags without certify should fail", ring, parcel, assertModifyFailure("setting master key flags without certify should fail", ring, builder.build(),
LogType.MSG_MF_ERROR_NO_CERTIFY); LogType.MSG_MF_ERROR_NO_CERTIFY);
} }
{ // a past expiry should fail { // a past expiry should fail
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createFlagsOrExpiryChange(keyId, null, new Date().getTime()/1000-10)); builder.addOrReplaceSubkeyChange(createFlagsOrExpiryChange(keyId, null, new Date().getTime() / 1000 - 10));
assertModifyFailure("setting subkey expiry to a past date should fail", ring, parcel, assertModifyFailure("setting subkey expiry to a past date should fail", ring, builder.build(),
LogType.MSG_MF_ERROR_PAST_EXPIRY); LogType.MSG_MF_ERROR_PAST_EXPIRY);
} }
@@ -637,10 +637,10 @@ public class PgpKeyOperationTest {
@Test @Test
public void testMasterRevoke() throws Exception { public void testMasterRevoke() throws Exception {
parcel.reset(); resetBuilder();
parcel.mRevokeSubKeys.add(ring.getMasterKeyId()); builder.addRevokeSubkey(ring.getMasterKeyId());
UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB); UncachedKeyRing modified = applyModificationWithChecks(builder.build(), ring, onlyA, onlyB);
Assert.assertEquals("no extra packets in original", 0, onlyA.size()); Assert.assertEquals("no extra packets in original", 0, onlyA.size());
Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size()); Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size());
@@ -669,11 +669,11 @@ public class PgpKeyOperationTest {
{ {
parcel.reset(); resetBuilder();
parcel.mRevokeSubKeys.add(123L); builder.addRevokeSubkey(123L);
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), 0); CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), 0);
UncachedKeyRing otherModified = op.modifySecretKeyRing(secretRing, cryptoInput, parcel).getRing(); UncachedKeyRing otherModified = op.modifySecretKeyRing(secretRing, cryptoInput, builder.build()).getRing();
Assert.assertNull("revoking a nonexistent subkey should fail", otherModified); Assert.assertNull("revoking a nonexistent subkey should fail", otherModified);
@@ -681,10 +681,10 @@ public class PgpKeyOperationTest {
{ // revoked second subkey { // revoked second subkey
parcel.reset(); resetBuilder();
parcel.mRevokeSubKeys.add(keyId); builder.addRevokeSubkey(keyId);
modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, modified = applyModificationWithChecks(builder.build(), ring, onlyA, onlyB,
CryptoInputParcel.createCryptoInputParcel(new Date(), passphrase)); CryptoInputParcel.createCryptoInputParcel(new Date(), passphrase));
Assert.assertEquals("no extra packets in original", 0, onlyA.size()); Assert.assertEquals("no extra packets in original", 0, onlyA.size());
@@ -705,11 +705,11 @@ public class PgpKeyOperationTest {
{ // re-add second subkey { // re-add second subkey
parcel.reset(); resetBuilder();
// re-certify the revoked subkey // re-certify the revoked subkey
parcel.mChangeSubKeys.add(SubkeyChange.createRecertifyChange(keyId, true)); builder.addOrReplaceSubkeyChange(createRecertifyChange(keyId, true));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertEquals("exactly two outdated packets in original", 2, onlyA.size()); Assert.assertEquals("exactly two outdated packets in original", 2, onlyA.size());
Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size()); Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size());
@@ -749,8 +749,8 @@ public class PgpKeyOperationTest {
public void testSubkeyStrip() throws Exception { public void testSubkeyStrip() throws Exception {
long keyId = KeyringTestingHelper.getSubkeyId(ring, 1); long keyId = KeyringTestingHelper.getSubkeyId(ring, 1);
parcel.mChangeSubKeys.add(SubkeyChange.createStripChange(keyId)); builder.addOrReplaceSubkeyChange(createStripChange(keyId));
applyModificationWithChecks(parcel, ring, onlyA, onlyB); applyModificationWithChecks(builder.build(), ring, onlyA, onlyB);
Assert.assertEquals("one extra packet in original", 1, onlyA.size()); Assert.assertEquals("one extra packet in original", 1, onlyA.size());
Assert.assertEquals("one extra packet in modified", 1, onlyB.size()); Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
@@ -775,8 +775,8 @@ public class PgpKeyOperationTest {
public void testMasterStrip() throws Exception { public void testMasterStrip() throws Exception {
long keyId = ring.getMasterKeyId(); long keyId = ring.getMasterKeyId();
parcel.mChangeSubKeys.add(SubkeyChange.createStripChange(keyId)); builder.addOrReplaceSubkeyChange(createStripChange(keyId));
applyModificationWithChecks(parcel, ring, onlyA, onlyB); applyModificationWithChecks(builder.build(), ring, onlyA, onlyB);
Assert.assertEquals("one extra packet in original", 1, onlyA.size()); Assert.assertEquals("one extra packet in original", 1, onlyA.size());
Assert.assertEquals("one extra packet in modified", 1, onlyB.size()); Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
@@ -803,9 +803,9 @@ public class PgpKeyOperationTest {
UncachedKeyRing modified; UncachedKeyRing modified;
{ // we should be able to change the stripped status of subkeys without passphrase { // we should be able to change the stripped status of subkeys without passphrase
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createStripChange(keyId)); builder.addOrReplaceSubkeyChange(createStripChange(keyId));
modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, modified = applyModificationWithChecks(builder.build(), ring, onlyA, onlyB,
CryptoInputParcel.createCryptoInputParcel()); CryptoInputParcel.createCryptoInputParcel());
Assert.assertEquals("one extra packet in modified", 1, onlyB.size()); Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket(); Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
@@ -816,11 +816,11 @@ public class PgpKeyOperationTest {
} }
{ // trying to edit a subkey with signing capability should fail { // trying to edit a subkey with signing capability should fail
parcel.reset(); resetBuilder();
parcel.mChangeSubKeys.add(SubkeyChange.createRecertifyChange(keyId, true)); builder.addOrReplaceSubkeyChange(createRecertifyChange(keyId, true));
assertModifyFailure("subkey modification for signing-enabled but stripped subkey should fail", assertModifyFailure("subkey modification for signing-enabled but stripped subkey should fail",
modified, parcel, LogType.MSG_MF_ERROR_SUB_STRIPPED); modified, builder.build(), LogType.MSG_MF_ERROR_SUB_STRIPPED);
} }
} }
@@ -829,51 +829,49 @@ public class PgpKeyOperationTest {
public void testKeyToSecurityToken() throws Exception { public void testKeyToSecurityToken() throws Exception {
// Special keyring for security token tests with 2048 bit RSA as a subkey // Special keyring for security token tests with 2048 bit RSA as a subkey
SaveKeyringParcel parcelKey = new SaveKeyringParcel(); SaveKeyringParcel.Builder keyBuilder = SaveKeyringParcel.buildNewKeyringParcel();
parcelKey.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( keyBuilder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.DSA, 2048, null, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.DSA, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
parcelKey.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( keyBuilder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.RSA, 2048, null, KeyFlags.SIGN_DATA, 0L)); Algorithm.RSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
parcelKey.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( keyBuilder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.RSA, 3072, null, KeyFlags.ENCRYPT_COMMS, 0L)); Algorithm.RSA, 3072, null, KeyFlags.ENCRYPT_COMMS, 0L));
parcelKey.mAddUserIds.add("yubikey"); keyBuilder.addUserId("yubikey");
parcelKey.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase)); keyBuilder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(passphrase));
PgpKeyOperation opSecurityToken = new PgpKeyOperation(null); PgpKeyOperation opSecurityToken = new PgpKeyOperation(null);
PgpEditKeyResult resultSecurityToken = opSecurityToken.createSecretKeyRing(parcelKey); PgpEditKeyResult resultSecurityToken = opSecurityToken.createSecretKeyRing(keyBuilder.build());
Assert.assertTrue("initial test key creation must succeed", resultSecurityToken.success()); Assert.assertTrue("initial test key creation must succeed", resultSecurityToken.success());
Assert.assertNotNull("initial test key creation must succeed", resultSecurityToken.getRing()); Assert.assertNotNull("initial test key creation must succeed", resultSecurityToken.getRing());
UncachedKeyRing ringSecurityToken = resultSecurityToken.getRing(); UncachedKeyRing ringSecurityToken = resultSecurityToken.getRing();
SaveKeyringParcel parcelSecurityToken = new SaveKeyringParcel();
parcelSecurityToken.mMasterKeyId = ringSecurityToken.getMasterKeyId();
parcelSecurityToken.mFingerprint = ringSecurityToken.getFingerprint();
UncachedKeyRing modified; UncachedKeyRing modified;
{ // moveKeyToSecurityToken should fail with BAD_NFC_ALGO when presented with the DSA-1024 key { // moveKeyToSecurityToken should fail with BAD_NFC_ALGO when presented with the DSA-1024 key
long keyId = KeyringTestingHelper.getSubkeyId(ringSecurityToken, 0); long keyId = KeyringTestingHelper.getSubkeyId(ringSecurityToken, 0);
parcelSecurityToken.reset(); SaveKeyringParcel.Builder securityTokenBuilder = SaveKeyringParcel.buildChangeKeyringParcel(
parcelSecurityToken.mChangeSubKeys.add(SubkeyChange.createMoveToSecurityTokenChange(keyId)); ringSecurityToken.getMasterKeyId(), ringSecurityToken.getFingerprint());
securityTokenBuilder.addOrReplaceSubkeyChange(SubkeyChange.createMoveToSecurityTokenChange(keyId));
assertModifyFailure("moveKeyToSecurityToken operation should fail on invalid key algorithm", ringSecurityToken, assertModifyFailure("moveKeyToSecurityToken operation should fail on invalid key algorithm", ringSecurityToken,
parcelSecurityToken, cryptoInput, LogType.MSG_MF_ERROR_BAD_SECURITY_TOKEN_ALGO); securityTokenBuilder.build(), cryptoInput, LogType.MSG_MF_ERROR_BAD_SECURITY_TOKEN_ALGO);
} }
long keyId = KeyringTestingHelper.getSubkeyId(ringSecurityToken, 1); long keyId = KeyringTestingHelper.getSubkeyId(ringSecurityToken, 1);
{ // moveKeyToSecurityToken should return a pending SECURITY_TOKEN_MOVE_KEY_TO_CARD result when presented with the RSA-2048 { // moveKeyToSecurityToken should return a pending SECURITY_TOKEN_MOVE_KEY_TO_CARD result when presented with the RSA-2048
// key, and then make key divert-to-card when it gets a serial in the cryptoInputParcel. // key, and then make key divert-to-card when it gets a serial in the cryptoInputParcel.
parcelSecurityToken.reset(); SaveKeyringParcel.Builder securityTokenBuilder = SaveKeyringParcel.buildChangeKeyringParcel(
parcelSecurityToken.mChangeSubKeys.add(SubkeyChange.createMoveToSecurityTokenChange(keyId)); ringSecurityToken.getMasterKeyId(), ringSecurityToken.getFingerprint());
securityTokenBuilder.addOrReplaceSubkeyChange(SubkeyChange.createMoveToSecurityTokenChange(keyId));
CanonicalizedSecretKeyRing secretRing = CanonicalizedSecretKeyRing secretRing =
new CanonicalizedSecretKeyRing(ringSecurityToken.getEncoded(), 0); new CanonicalizedSecretKeyRing(ringSecurityToken.getEncoded(), 0);
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, parcelSecurityToken); PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, securityTokenBuilder.build());
Assert.assertTrue("moveKeyToSecurityToken operation should be pending", result.isPending()); Assert.assertTrue("moveKeyToSecurityToken operation should be pending", result.isPending());
Assert.assertEquals("required input should be RequiredInputType.SECURITY_TOKEN_MOVE_KEY_TO_CARD", Assert.assertEquals("required input should be RequiredInputType.SECURITY_TOKEN_MOVE_KEY_TO_CARD",
result.getRequiredInputParcel().mType, RequiredInputType.SECURITY_TOKEN_MOVE_KEY_TO_CARD); result.getRequiredInputParcel().mType, RequiredInputType.SECURITY_TOKEN_MOVE_KEY_TO_CARD);
@@ -889,7 +887,7 @@ public class PgpKeyOperationTest {
CryptoInputParcel inputParcel = CryptoInputParcel.createCryptoInputParcel(); CryptoInputParcel inputParcel = CryptoInputParcel.createCryptoInputParcel();
inputParcel = inputParcel.withCryptoData(keyIdBytes, serial); inputParcel = inputParcel.withCryptoData(keyIdBytes, serial);
modified = applyModificationWithChecks(parcelSecurityToken, ringSecurityToken, onlyA, onlyB, inputParcel); modified = applyModificationWithChecks(securityTokenBuilder.build(), ringSecurityToken, onlyA, onlyB, inputParcel);
Assert.assertEquals("one extra packet in modified", 1, onlyB.size()); Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket(); Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
Assert.assertEquals("new packet should have GNU_DUMMY S2K type", Assert.assertEquals("new packet should have GNU_DUMMY S2K type",
@@ -901,13 +899,14 @@ public class PgpKeyOperationTest {
} }
{ // editing a signing subkey requires a primary key binding sig -> pendinginput { // editing a signing subkey requires a primary key binding sig -> pendinginput
parcelSecurityToken.reset(); SaveKeyringParcel.Builder securityTokenBuilder = SaveKeyringParcel.buildChangeKeyringParcel(
parcelSecurityToken.mChangeSubKeys.add(SubkeyChange.createRecertifyChange(keyId, true)); ringSecurityToken.getMasterKeyId(), ringSecurityToken.getFingerprint());
securityTokenBuilder.addOrReplaceSubkeyChange(SubkeyChange.createRecertifyChange(keyId, true));
CanonicalizedSecretKeyRing secretRing = CanonicalizedSecretKeyRing secretRing =
new CanonicalizedSecretKeyRing(modified.getEncoded(), 0); new CanonicalizedSecretKeyRing(modified.getEncoded(), 0);
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, parcelSecurityToken); PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, securityTokenBuilder.build());
Assert.assertTrue("moveKeyToSecurityToken operation should be pending", result.isPending()); Assert.assertTrue("moveKeyToSecurityToken operation should be pending", result.isPending());
Assert.assertEquals("required input should be RequiredInputType.SECURITY_TOKEN_SIGN", Assert.assertEquals("required input should be RequiredInputType.SECURITY_TOKEN_SIGN",
RequiredInputType.SECURITY_TOKEN_SIGN, result.getRequiredInputParcel().mType); RequiredInputType.SECURITY_TOKEN_SIGN, result.getRequiredInputParcel().mType);
@@ -922,10 +921,8 @@ public class PgpKeyOperationTest {
String uid = ring.getPublicKey().getUnorderedUserIds().get(1); String uid = ring.getPublicKey().getUnorderedUserIds().get(1);
{ // revoke second user id { // revoke second user id
builder.addRevokeUserId(uid);
parcel.mRevokeUserIds.add(uid); modified = applyModificationWithChecks(builder.build(), ring, onlyA, onlyB);
modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB);
Assert.assertEquals("no extra packets in original", 0, onlyA.size()); Assert.assertEquals("no extra packets in original", 0, onlyA.size());
Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size()); Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size());
@@ -943,20 +940,20 @@ public class PgpKeyOperationTest {
{ // re-add second user id { // re-add second user id
parcel.reset(); resetBuilder();
parcel.mChangePrimaryUserId = uid; builder.setChangePrimaryUserId(uid);
assertModifyFailure("setting primary user id to a revoked user id should fail", modified, parcel, assertModifyFailure("setting primary user id to a revoked user id should fail", modified, builder.build(),
LogType.MSG_MF_ERROR_REVOKED_PRIMARY); LogType.MSG_MF_ERROR_REVOKED_PRIMARY);
} }
{ // re-add second user id { // re-add second user id
parcel.reset(); resetBuilder();
parcel.mAddUserIds.add(uid); builder.addUserId(uid);
applyModificationWithChecks(parcel, modified, onlyA, onlyB); applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertEquals("exactly two outdated packets in original", 2, onlyA.size()); Assert.assertEquals("exactly two outdated packets in original", 2, onlyA.size());
Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size()); Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size());
@@ -986,10 +983,10 @@ public class PgpKeyOperationTest {
} }
{ // revocation of non-existent user id should fail { // revocation of non-existent user id should fail
parcel.reset(); resetBuilder();
parcel.mRevokeUserIds.add("nonexistent"); builder.addRevokeUserId("nonexistent");
assertModifyFailure("revocation of nonexistent user id should fail", modified, parcel, assertModifyFailure("revocation of nonexistent user id should fail", modified, builder.build(),
LogType.MSG_MF_ERROR_NOEXIST_REVOKE); LogType.MSG_MF_ERROR_NOEXIST_REVOKE);
} }
@@ -999,15 +996,15 @@ public class PgpKeyOperationTest {
public void testUserIdAdd() throws Exception { public void testUserIdAdd() throws Exception {
{ {
parcel.mAddUserIds.add(""); builder.addUserId("");
assertModifyFailure("adding an empty user id should fail", ring, parcel, assertModifyFailure("adding an empty user id should fail", ring, builder.build(),
LogType.MSG_MF_UID_ERROR_EMPTY); LogType.MSG_MF_UID_ERROR_EMPTY);
} }
parcel.reset(); resetBuilder();
parcel.mAddUserIds.add("rainbow"); builder.addUserId("rainbow");
UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB); UncachedKeyRing modified = applyModificationWithChecks(builder.build(), ring, onlyA, onlyB);
Assert.assertTrue("keyring must contain added user id", Assert.assertTrue("keyring must contain added user id",
modified.getPublicKey().getUnorderedUserIds().contains("rainbow")); modified.getPublicKey().getUnorderedUserIds().contains("rainbow"));
@@ -1036,12 +1033,12 @@ public class PgpKeyOperationTest {
public void testUserAttributeAdd() throws Exception { public void testUserAttributeAdd() throws Exception {
{ {
parcel.mAddUserAttribute.add(WrappedUserAttribute.fromData(new byte[0])); builder.addUserAttribute(WrappedUserAttribute.fromData(new byte[0]));
assertModifyFailure("adding an empty user attribute should fail", ring, parcel, assertModifyFailure("adding an empty user attribute should fail", ring, builder.build(),
LogType.MSG_MF_UAT_ERROR_EMPTY); LogType.MSG_MF_UAT_ERROR_EMPTY);
} }
parcel.reset(); resetBuilder();
Random r = new Random(); Random r = new Random();
int type = r.nextInt(110)+2; // any type except image attribute, to avoid interpretation of these int type = r.nextInt(110)+2; // any type except image attribute, to avoid interpretation of these
@@ -1049,9 +1046,9 @@ public class PgpKeyOperationTest {
new Random().nextBytes(data); new Random().nextBytes(data);
WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data); WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data);
parcel.mAddUserAttribute.add(uat); builder.addUserAttribute(uat);
UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB); UncachedKeyRing modified = applyModificationWithChecks(builder.build(), ring, onlyA, onlyB);
Assert.assertEquals("no extra packets in original", 0, onlyA.size()); Assert.assertEquals("no extra packets in original", 0, onlyA.size());
Assert.assertEquals("exactly two extra packets in modified", 2, onlyB.size()); Assert.assertEquals("exactly two extra packets in modified", 2, onlyB.size());
@@ -1082,7 +1079,7 @@ public class PgpKeyOperationTest {
// applying the same modification AGAIN should not add more certifications but drop those // applying the same modification AGAIN should not add more certifications but drop those
// as duplicates // as duplicates
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB, applyModificationWithChecks(builder.build(), modified, onlyA, onlyB,
CryptoInputParcel.createCryptoInputParcel(new Date(), passphrase), true, false); CryptoInputParcel.createCryptoInputParcel(new Date(), passphrase), true, false);
Assert.assertEquals("duplicate modification: one extra packet in original", 1, onlyA.size()); Assert.assertEquals("duplicate modification: one extra packet in original", 1, onlyA.size());
@@ -1103,20 +1100,20 @@ public class PgpKeyOperationTest {
String uid = ring.getPublicKey().getUnorderedUserIds().get(1); String uid = ring.getPublicKey().getUnorderedUserIds().get(1);
{ // first part, add new user id which is also primary { // first part, add new user id which is also primary
parcel.mAddUserIds.add("jack"); builder.addUserId("jack");
parcel.mChangePrimaryUserId = "jack"; builder.setChangePrimaryUserId("jack");
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertEquals("primary user id must be the one added", Assert.assertEquals("primary user id must be the one added",
"jack", modified.getPublicKey().getPrimaryUserId()); "jack", modified.getPublicKey().getPrimaryUserId());
} }
{ // second part, change primary to a different one { // second part, change primary to a different one
parcel.reset(); resetBuilder();
parcel.mChangePrimaryUserId = uid; builder.setChangePrimaryUserId(uid);
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB);
Assert.assertEquals("old keyring must have two outdated certificates", 2, onlyA.size()); Assert.assertEquals("old keyring must have two outdated certificates", 2, onlyA.size());
Assert.assertEquals("new keyring must have two new packets", 2, onlyB.size()); Assert.assertEquals("new keyring must have two new packets", 2, onlyB.size());
@@ -1126,15 +1123,11 @@ public class PgpKeyOperationTest {
} }
{ // third part, change primary to a non-existent one { // third part, change primary to a non-existent one
parcel.reset(); resetBuilder();
//noinspection SpellCheckingInspection //noinspection SpellCheckingInspection
parcel.mChangePrimaryUserId = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; builder.setChangePrimaryUserId("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
if (parcel.mChangePrimaryUserId.equals(passphrase)) {
parcel.mChangePrimaryUserId += "A";
}
assertModifyFailure("changing primary user id to a non-existent one should fail", assertModifyFailure("changing primary user id to a non-existent one should fail",
ring, parcel, LogType.MSG_MF_ERROR_NOEXIST_PRIMARY); ring, builder.build(), LogType.MSG_MF_ERROR_NOEXIST_PRIMARY);
} }
// check for revoked primary user id already done in revoke test // check for revoked primary user id already done in revoke test
@@ -1145,9 +1138,9 @@ public class PgpKeyOperationTest {
public void testPassphraseChange() throws Exception { public void testPassphraseChange() throws Exception {
// change passphrase to empty // change passphrase to empty
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase())); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase()));
// note that canonicalization here necessarily strips the empty notation packet // note that canonicalization here necessarily strips the empty notation packet
UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, cryptoInput); UncachedKeyRing modified = applyModificationWithChecks(builder.build(), ring, onlyA, onlyB, cryptoInput);
Assert.assertEquals("exactly three packets should have been modified (the secret keys)", Assert.assertEquals("exactly three packets should have been modified (the secret keys)",
3, onlyB.size()); 3, onlyB.size());
@@ -1160,15 +1153,15 @@ public class PgpKeyOperationTest {
// modify keyring, change to non-empty passphrase // modify keyring, change to non-empty passphrase
Passphrase otherPassphrase = TestingUtils.genPassphrase(true); Passphrase otherPassphrase = TestingUtils.genPassphrase(true);
CryptoInputParcel otherCryptoInput = CryptoInputParcel.createCryptoInputParcel(otherPassphrase); CryptoInputParcel otherCryptoInput = CryptoInputParcel.createCryptoInputParcel(otherPassphrase);
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(otherPassphrase)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(otherPassphrase));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB, modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB,
CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase())); CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()));
Assert.assertEquals("exactly three packets should have been modified (the secret keys)", Assert.assertEquals("exactly three packets should have been modified (the secret keys)",
3, onlyB.size()); 3, onlyB.size());
{ // quick check to make sure no two secret keys have the same IV { // quick check to make sure no two secret keys have the same IV
HashSet<ByteBuffer> ivs = new HashSet<ByteBuffer>(); HashSet<ByteBuffer> ivs = new HashSet<>();
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
SecretKeyPacket p = (SecretKeyPacket) new BCPGInputStream( SecretKeyPacket p = (SecretKeyPacket) new BCPGInputStream(
new ByteArrayInputStream(onlyB.get(i).buf)).readPacket(); new ByteArrayInputStream(onlyB.get(i).buf)).readPacket();
@@ -1186,7 +1179,7 @@ public class PgpKeyOperationTest {
PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag); PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag);
Passphrase otherPassphrase2 = TestingUtils.genPassphrase(true); Passphrase otherPassphrase2 = TestingUtils.genPassphrase(true);
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(otherPassphrase2)); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(otherPassphrase2));
{ {
// if we replace a secret key with one without passphrase // if we replace a secret key with one without passphrase
modified = KeyringTestingHelper.removePacket(modified, sKeyNoPassphrase.position); modified = KeyringTestingHelper.removePacket(modified, sKeyNoPassphrase.position);
@@ -1195,7 +1188,7 @@ public class PgpKeyOperationTest {
// we should still be able to modify it (and change its passphrase) without errors // we should still be able to modify it (and change its passphrase) without errors
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), 0); CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), 0);
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, otherCryptoInput, parcel); PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, otherCryptoInput, builder.build());
Assert.assertTrue("key modification must succeed", result.success()); Assert.assertTrue("key modification must succeed", result.success());
Assert.assertFalse("log must not contain a warning", Assert.assertFalse("log must not contain a warning",
result.getLog().containsWarnings()); result.getLog().containsWarnings());
@@ -1212,7 +1205,7 @@ public class PgpKeyOperationTest {
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), 0); CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), 0);
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, PgpEditKeyResult result = op.modifySecretKeyRing(secretRing,
CryptoInputParcel.createCryptoInputParcel(otherPassphrase2), parcel); CryptoInputParcel.createCryptoInputParcel(otherPassphrase2), builder.build());
Assert.assertTrue("key modification must succeed", result.success()); Assert.assertTrue("key modification must succeed", result.success());
Assert.assertTrue("log must contain a failed passphrase change warning", Assert.assertTrue("log must contain a failed passphrase change warning",
result.getLog().containsType(LogType.MSG_MF_PASSPHRASE_FAIL)); result.getLog().containsType(LogType.MSG_MF_PASSPHRASE_FAIL));
@@ -1225,10 +1218,10 @@ public class PgpKeyOperationTest {
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), 0); CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), 0);
parcel.mAddUserIds.add("discord"); builder.addUserId("discord");
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, PgpEditKeyResult result = op.modifySecretKeyRing(secretRing,
CryptoInputParcel.createCryptoInputParcel(new Date()), parcel); CryptoInputParcel.createCryptoInputParcel(new Date()), builder.build());
Assert.assertFalse("non-restricted operations should fail without passphrase", result.success()); Assert.assertFalse("non-restricted operations should fail without passphrase", result.success());
} }
@@ -1299,8 +1292,8 @@ public class PgpKeyOperationTest {
CanonicalizedKeyRing canonicalized = inputKeyRing.canonicalize(new OperationLog(), 0); CanonicalizedKeyRing canonicalized = inputKeyRing.canonicalize(new OperationLog(), 0);
Assert.assertNotNull("canonicalization must succeed", canonicalized); Assert.assertNotNull("canonicalization must succeed", canonicalized);
ArrayList onlyA = new ArrayList<RawPacket>(); ArrayList onlyA = new ArrayList<>();
ArrayList onlyB = new ArrayList<RawPacket>(); ArrayList onlyB = new ArrayList<>();
//noinspection unchecked //noinspection unchecked
Assert.assertTrue("keyrings differ", !KeyringTestingHelper.diffKeyrings( Assert.assertTrue("keyrings differ", !KeyringTestingHelper.diffKeyrings(
expectedKeyRing.getEncoded(), expectedKeyRing.getEncoded(), onlyA, onlyB)); expectedKeyRing.getEncoded(), expectedKeyRing.getEncoded(), onlyA, onlyB));

View File

@@ -96,27 +96,27 @@ public class UncachedKeyringCanonicalizeTest {
Security.insertProviderAt(new BouncyCastleProvider(), 1); Security.insertProviderAt(new BouncyCastleProvider(), 1);
ShadowLog.stream = System.out; ShadowLog.stream = System.out;
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L));
parcel.mAddUserIds.add("twi"); builder.addUserId("twi");
parcel.mAddUserIds.add("pink"); builder.addUserId("pink");
{ {
WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(100, WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(100,
"sunshine, sunshine, ladybugs awake~".getBytes()); "sunshine, sunshine, ladybugs awake~".getBytes());
parcel.mAddUserAttribute.add(uat); builder.addUserAttribute(uat);
} }
// passphrase is tested in PgpKeyOperationTest, just use empty here // passphrase is tested in PgpKeyOperationTest, just use empty here
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase())); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase()));
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
PgpEditKeyResult result = op.createSecretKeyRing(parcel); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
Assert.assertTrue("initial test key creation must succeed", result.success()); Assert.assertTrue("initial test key creation must succeed", result.success());
staticRing = result.getRing(); staticRing = result.getRing();
Assert.assertNotNull("initial test key creation must succeed", staticRing); Assert.assertNotNull("initial test key creation must succeed", staticRing);
@@ -352,14 +352,14 @@ public class UncachedKeyringCanonicalizeTest {
@Test public void testForeignSignature() throws Exception { @Test public void testForeignSignature() throws Exception {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddUserIds.add("trix"); builder.addUserId("trix");
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
OperationResult.OperationLog log = new OperationResult.OperationLog(); OperationResult.OperationLog log = new OperationResult.OperationLog();
UncachedKeyRing foreign = op.createSecretKeyRing(parcel).getRing(); UncachedKeyRing foreign = op.createSecretKeyRing(builder.build()).getRing();
Assert.assertNotNull("initial test key creation must succeed", foreign); Assert.assertNotNull("initial test key creation must succeed", foreign);
PGPSecretKey foreignSecretKey = PGPSecretKey foreignSecretKey =

View File

@@ -89,7 +89,7 @@ public class UncachedKeyringMergeTest {
ArrayList<RawPacket> onlyB = new ArrayList<>(); ArrayList<RawPacket> onlyB = new ArrayList<>();
OperationResult.OperationLog log = new OperationResult.OperationLog(); OperationResult.OperationLog log = new OperationResult.OperationLog();
PgpKeyOperation op; PgpKeyOperation op;
SaveKeyringParcel parcel; SaveKeyringParcel.Builder builder;
@BeforeClass @BeforeClass
public static void setUpOnce() throws Exception { public static void setUpOnce() throws Exception {
@@ -97,43 +97,42 @@ public class UncachedKeyringMergeTest {
ShadowLog.stream = System.out; ShadowLog.stream = System.out;
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddUserIds.add("twi"); builder.addUserId("twi");
parcel.mAddUserIds.add("pink"); builder.addUserId("pink");
{ {
WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(100, WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(100,
"sunshine, sunshine, ladybugs awake~".getBytes()); "sunshine, sunshine, ladybugs awake~".getBytes());
parcel.mAddUserAttribute.add(uat); builder.addUserAttribute(uat);
} }
// passphrase is tested in PgpKeyOperationTest, just use empty here // passphrase is tested in PgpKeyOperationTest, just use empty here
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase())); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase()));
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
OperationResult.OperationLog log = new OperationResult.OperationLog(); OperationResult.OperationLog log = new OperationResult.OperationLog();
PgpEditKeyResult result = op.createSecretKeyRing(parcel); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
staticRingA = result.getRing(); staticRingA = result.getRing();
staticRingA = staticRingA.canonicalize(new OperationLog(), 0).getUncachedKeyRing(); staticRingA = staticRingA.canonicalize(new OperationLog(), 0).getUncachedKeyRing();
} }
{ {
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddUserIds.add("shy"); builder.addUserId("shy");
// passphrase is tested in PgpKeyOperationTest, just use empty here // passphrase is tested in PgpKeyOperationTest, just use empty here
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase())); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase()));
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
OperationResult.OperationLog log = new OperationResult.OperationLog(); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
PgpEditKeyResult result = op.createSecretKeyRing(parcel);
staticRingB = result.getRing(); staticRingB = result.getRing();
staticRingB = staticRingB.canonicalize(new OperationLog(), 0).getUncachedKeyRing(); staticRingB = staticRingB.canonicalize(new OperationLog(), 0).getUncachedKeyRing();
} }
@@ -155,10 +154,11 @@ public class UncachedKeyringMergeTest {
// setting up some parameters just to reduce code duplication // setting up some parameters just to reduce code duplication
op = new PgpKeyOperation(new ProgressScaler(null, 0, 100, 100)); op = new PgpKeyOperation(new ProgressScaler(null, 0, 100, 100));
// set this up, gonna need it more than once resetBuilder();
parcel = new SaveKeyringParcel(); }
parcel.mMasterKeyId = ringA.getMasterKeyId();
parcel.mFingerprint = ringA.getFingerprint(); private void resetBuilder() {
builder = SaveKeyringParcel.buildChangeKeyringParcel(ringA.getMasterKeyId(), ringA.getFingerprint());
} }
public void testSelfNoOp() throws Exception { public void testSelfNoOp() throws Exception {
@@ -190,15 +190,15 @@ public class UncachedKeyringMergeTest {
CanonicalizedSecretKeyRing secretRing = CanonicalizedSecretKeyRing secretRing =
new CanonicalizedSecretKeyRing(ringA.getEncoded(), 0); new CanonicalizedSecretKeyRing(ringA.getEncoded(), 0);
parcel.reset(); resetBuilder();
parcel.mAddUserIds.add("flim"); builder.addUserId("flim");
modifiedA = op.modifySecretKeyRing(secretRing, modifiedA = op.modifySecretKeyRing(secretRing,
CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), parcel).getRing(); CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), builder.build()).getRing();
parcel.reset(); resetBuilder();
parcel.mAddUserIds.add("flam"); builder.addUserId("flam");
modifiedB = op.modifySecretKeyRing(secretRing, modifiedB = op.modifySecretKeyRing(secretRing,
CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), parcel).getRing(); CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), builder.build()).getRing();
} }
{ // merge A into base { // merge A into base
@@ -232,13 +232,13 @@ public class UncachedKeyringMergeTest {
{ {
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ringA.getEncoded(), 0); CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ringA.getEncoded(), 0);
parcel.reset(); resetBuilder();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
modifiedA = op.modifySecretKeyRing(secretRing, modifiedA = op.modifySecretKeyRing(secretRing,
CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), parcel).getRing(); CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), builder.build()).getRing();
modifiedB = op.modifySecretKeyRing(secretRing, modifiedB = op.modifySecretKeyRing(secretRing,
CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), parcel).getRing(); CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), builder.build()).getRing();
subKeyIdA = KeyringTestingHelper.getSubkeyId(modifiedA, 2); subKeyIdA = KeyringTestingHelper.getSubkeyId(modifiedA, 2);
subKeyIdB = KeyringTestingHelper.getSubkeyId(modifiedB, 2); subKeyIdB = KeyringTestingHelper.getSubkeyId(modifiedB, 2);
@@ -275,12 +275,12 @@ public class UncachedKeyringMergeTest {
public void testAddedKeySignature() throws Exception { public void testAddedKeySignature() throws Exception {
final UncachedKeyRing modified; { final UncachedKeyRing modified; {
parcel.reset(); resetBuilder();
parcel.mRevokeSubKeys.add(KeyringTestingHelper.getSubkeyId(ringA, 1)); builder.addRevokeSubkey(KeyringTestingHelper.getSubkeyId(ringA, 1));
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing( CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(
ringA.getEncoded(), 0); ringA.getEncoded(), 0);
modified = op.modifySecretKeyRing(secretRing, modified = op.modifySecretKeyRing(secretRing,
CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), parcel).getRing(); CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), builder.build()).getRing();
} }
{ {
@@ -368,7 +368,7 @@ public class UncachedKeyringMergeTest {
public void testAddedUserAttributeSignature() throws Exception { public void testAddedUserAttributeSignature() throws Exception {
final UncachedKeyRing modified; { final UncachedKeyRing modified; {
parcel.reset(); resetBuilder();
Random r = new Random(); Random r = new Random();
int type = r.nextInt(110)+1; int type = r.nextInt(110)+1;
@@ -376,12 +376,12 @@ public class UncachedKeyringMergeTest {
new Random().nextBytes(data); new Random().nextBytes(data);
WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data); WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data);
parcel.mAddUserAttribute.add(uat); builder.addUserAttribute(uat);
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing( CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(
ringA.getEncoded(), 0); ringA.getEncoded(), 0);
modified = op.modifySecretKeyRing(secretRing, modified = op.modifySecretKeyRing(secretRing,
CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), parcel).getRing(); CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), builder.build()).getRing();
} }
{ {

View File

@@ -54,16 +54,16 @@ public class UncachedKeyringTest {
Security.insertProviderAt(new BouncyCastleProvider(), 1); Security.insertProviderAt(new BouncyCastleProvider(), 1);
ShadowLog.stream = System.out; ShadowLog.stream = System.out;
SaveKeyringParcel parcel = new SaveKeyringParcel(); SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
parcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd( builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L));
parcel.mAddUserIds.add("twi"); builder.addUserId("twi");
parcel.mAddUserIds.add("pink"); builder.addUserId("pink");
{ {
Random r = new Random(); Random r = new Random();
int type = r.nextInt(110)+1; int type = r.nextInt(110)+1;
@@ -71,13 +71,13 @@ public class UncachedKeyringTest {
new Random().nextBytes(data); new Random().nextBytes(data);
WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data); WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data);
parcel.mAddUserAttribute.add(uat); builder.addUserAttribute(uat);
} }
// passphrase is tested in PgpKeyOperationTest, just use empty here // passphrase is tested in PgpKeyOperationTest, just use empty here
parcel.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase())); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase()));
PgpKeyOperation op = new PgpKeyOperation(null); PgpKeyOperation op = new PgpKeyOperation(null);
PgpEditKeyResult result = op.createSecretKeyRing(parcel); PgpEditKeyResult result = op.createSecretKeyRing(builder.build());
staticRing = result.getRing(); staticRing = result.getRing();
staticPubRing = staticRing.extractPublicKeyRing(); staticPubRing = staticRing.extractPublicKeyRing();