use autovalue for SubkeyAdd and SubkeyChange

This commit is contained in:
Vincent Breitmoser
2017-05-22 13:44:58 +02:00
parent 5f89d28937
commit 147e4dbee7
20 changed files with 239 additions and 267 deletions

View File

@@ -24,6 +24,7 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.sufficientlysecure.keychain.securitytoken.KeyFormat;
import org.sufficientlysecure.keychain.securitytoken.RSAKeyFormat;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import java.io.File;
import java.net.Proxy;
@@ -179,11 +180,11 @@ public final class Constants {
* Default key configuration: 3072 bit RSA (certify, sign, encrypt)
*/
public static void addDefaultSubkeys(SaveKeyringParcel saveKeyringParcel) {
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
saveKeyringParcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
3072, null, KeyFlags.CERTIFY_OTHER, 0L));
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
saveKeyringParcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
3072, null, KeyFlags.SIGN_DATA, 0L));
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
saveKeyringParcel.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
3072, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L));
}

View File

@@ -29,6 +29,7 @@ import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.security.spec.ECGenParameterSpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
@@ -81,6 +82,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenKeyToCardOperationsBuilder;
@@ -166,17 +168,17 @@ public class PgpKeyOperation {
try {
// Some safety checks
if (add.mAlgorithm == Algorithm.ECDH || add.mAlgorithm == Algorithm.ECDSA) {
if (add.mCurve == null) {
if (add.getAlgorithm() == Algorithm.ECDH || add.getAlgorithm() == Algorithm.ECDSA) {
if (add.getCurve() == null) {
log.add(LogType.MSG_CR_ERROR_NO_CURVE, indent);
return null;
}
} else {
if (add.mKeySize == null) {
if (add.getKeySize() == null) {
log.add(LogType.MSG_CR_ERROR_NO_KEYSIZE, indent);
return null;
}
if (add.mKeySize < 2048) {
if (add.getKeySize() < 2048) {
log.add(LogType.MSG_CR_ERROR_KEYSIZE_2048, indent);
return null;
}
@@ -185,27 +187,27 @@ public class PgpKeyOperation {
int algorithm;
KeyPairGenerator keyGen;
switch (add.mAlgorithm) {
switch (add.getAlgorithm()) {
case DSA: {
if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
if ((add.getFlags() & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
log.add(LogType.MSG_CR_ERROR_FLAGS_DSA, indent);
return null;
}
progress(R.string.progress_generating_dsa, 30);
keyGen = KeyPairGenerator.getInstance("DSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
keyGen.initialize(add.mKeySize, new SecureRandom());
keyGen.initialize(add.getKeySize(), new SecureRandom());
algorithm = PGPPublicKey.DSA;
break;
}
case ELGAMAL: {
if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
if ((add.getFlags() & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
log.add(LogType.MSG_CR_ERROR_FLAGS_ELGAMAL, indent);
return null;
}
progress(R.string.progress_generating_elgamal, 30);
keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
BigInteger p = Primes.getBestPrime(add.mKeySize);
BigInteger p = Primes.getBestPrime(add.getKeySize());
BigInteger g = new BigInteger("2");
ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g);
@@ -218,19 +220,19 @@ public class PgpKeyOperation {
case RSA: {
progress(R.string.progress_generating_rsa, 30);
keyGen = KeyPairGenerator.getInstance("RSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
keyGen.initialize(add.mKeySize, new SecureRandom());
keyGen.initialize(add.getKeySize(), new SecureRandom());
algorithm = PGPPublicKey.RSA_GENERAL;
break;
}
case ECDSA: {
if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
if ((add.getFlags() & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
log.add(LogType.MSG_CR_ERROR_FLAGS_ECDSA, indent);
return null;
}
progress(R.string.progress_generating_ecdsa, 30);
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve);
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.getCurve());
keyGen = KeyPairGenerator.getInstance("ECDSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
keyGen.initialize(ecParamSpec, new SecureRandom());
@@ -240,12 +242,12 @@ public class PgpKeyOperation {
case ECDH: {
// make sure there are no sign or certify flags set
if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
if ((add.getFlags() & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
log.add(LogType.MSG_CR_ERROR_FLAGS_ECDH, indent);
return null;
}
progress(R.string.progress_generating_ecdh, 30);
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve);
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.getCurve());
keyGen = KeyPairGenerator.getInstance("ECDH", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
keyGen.initialize(ecParamSpec, new SecureRandom());
@@ -296,12 +298,12 @@ public class PgpKeyOperation {
}
SubkeyAdd add = saveParcel.mAddSubKeys.remove(0);
if ((add.mFlags & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
if ((add.getFlags() & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
log.add(LogType.MSG_CR_ERROR_NO_CERTIFY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (add.mExpiry == null) {
if (add.getExpiry() == null) {
log.add(LogType.MSG_CR_ERROR_NULL_EXPIRY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
@@ -337,7 +339,7 @@ public class PgpKeyOperation {
subProgressPush(50, 100);
CryptoInputParcel cryptoInput = CryptoInputParcel.createCryptoInputParcel(creationTime, new Passphrase(""));
return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, cryptoInput, saveParcel, log, indent);
return internal(sKR, masterSecretKey, add.getFlags(), add.getExpiry(), cryptoInput, saveParcel, log, indent);
} catch (PGPException e) {
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
@@ -417,25 +419,25 @@ public class PgpKeyOperation {
boolean hasSign = false;
boolean hasEncrypt = false;
boolean hasAuth = false;
for(SaveKeyringParcel.SubkeyChange change : saveParcel.mChangeSubKeys) {
if (change.mMoveKeyToSecurityToken) {
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.mKeyId).rewind();
buf.putLong(change.getSubKeyId()).rewind();
byte[] serialNumber = cryptoInput.getCryptoData().get(buf);
if (serialNumber != null) {
change.mMoveKeyToSecurityToken = false;
change.mSecurityTokenSerialNo = serialNumber;
saveParcel.addOrReplaceSubkeyChange(
SubkeyChange.createSecurityTokenSerialNo(change.getSubKeyId(), serialNumber));
}
}
if (change.mMoveKeyToSecurityToken) {
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.mKeyId);
CanonicalizedSecretKey wsK = wsKR.getSecretKey(change.getSubKeyId());
if ((wsK.canSign() || wsK.canCertify())) {
if (hasSign) {
@@ -806,62 +808,62 @@ public class PgpKeyOperation {
progress(R.string.progress_modify_subkeychange, (i-1) * (100 / saveParcel.mChangeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_CHANGE,
indent, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId);
PGPSecretKey sKey = sKR.getSecretKey(change.getSubKeyId());
if (sKey == null) {
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (change.mDummyStrip) {
if (change.getDummyStrip()) {
// IT'S DANGEROUS~
// no really, it is. this operation irrevocably removes the private key data from the key
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
} else if (change.mMoveKeyToSecurityToken) {
} else if (change.getMoveKeyToSecurityToken()) {
if (checkSecurityTokenCompatibility(sKey, log, indent + 1)) {
log.add(LogType.MSG_MF_KEYTOCARD_START, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
nfcKeyToCardOps.addSubkey(change.mKeyId);
KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
nfcKeyToCardOps.addSubkey(change.getSubKeyId());
} else {
// Appropriate log message already set by checkSecurityTokenCompatibility
return new PgpEditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
}
} else if (change.mSecurityTokenSerialNo != null) {
} else if (change.getSecurityTokenSerialNo() != null) {
// NOTE: Does this code get executed? Or always handled in internalRestricted?
if (change.mSecurityTokenSerialNo.length != 16) {
if (change.getSecurityTokenSerialNo().length != 16) {
log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
log.add(LogType.MSG_MF_KEYTOCARD_FINISH, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(change.mKeyId),
Hex.toHexString(change.mSecurityTokenSerialNo, 8, 6));
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.mSecurityTokenSerialNo);
KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()),
Hex.toHexString(change.getSecurityTokenSerialNo(), 8, 6));
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.getSecurityTokenSerialNo());
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
}
// This doesn't concern us any further
if (!change.mRecertify && (change.mExpiry == null && change.mFlags == null)) {
if (!change.getRecertify() && (change.getExpiry() == null && change.getFlags() == null)) {
continue;
}
// expiry must not be in the past
if (change.mExpiry != null && change.mExpiry != 0 &&
new Date(change.mExpiry*1000).before(new Date())) {
if (change.getExpiry() != null && change.getExpiry() != 0 &&
new Date(change.getExpiry() * 1000).before(new Date())) {
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
// if this is the master key, update uid certificates instead
if (change.mKeyId == masterPublicKey.getKeyID()) {
int flags = change.mFlags == null ? masterKeyFlags : change.mFlags;
long expiry = change.mExpiry == null ? masterKeyExpiry : change.mExpiry;
if (change.getSubKeyId() == masterPublicKey.getKeyID()) {
int flags = change.getFlags() == null ? masterKeyFlags : change.getFlags();
long expiry = change.getExpiry() == null ? masterKeyExpiry : change.getExpiry();
if ((flags & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
log.add(LogType.MSG_MF_ERROR_NO_CERTIFY, indent + 1);
@@ -886,22 +888,22 @@ public class PgpKeyOperation {
PGPPublicKey pKey = sKey.getPublicKey();
// keep old flags, or replace with new ones
int flags = change.mFlags == null ? readKeyFlags(pKey) : change.mFlags;
int flags = change.getFlags() == null ? readKeyFlags(pKey) : change.getFlags();
long expiry;
if (change.mExpiry == null) {
if (change.getExpiry() == null) {
long valid = pKey.getValidSeconds();
expiry = valid == 0
? 0
: pKey.getCreationTime().getTime() / 1000 + pKey.getValidSeconds();
} else {
expiry = change.mExpiry;
expiry = change.getExpiry();
}
// drop all old signatures, they will be superseded by the new one
//noinspection unchecked
for (PGPSignature sig : new IterableIterator<PGPSignature>(pKey.getSignatures())) {
// special case: if there is a revocation, don't use expiry from before
if ( (change.mExpiry == null || change.mExpiry == 0L)
if ( (change.getExpiry() == null || change.getExpiry() == 0L)
&& sig.getSignatureType() == PGPSignature.SUBKEY_REVOCATION) {
expiry = 0;
}
@@ -917,7 +919,7 @@ public class PgpKeyOperation {
// super special case: subkey is allowed to sign, but isn't available
if (subPrivateKey == null) {
log.add(LogType.MSG_MF_ERROR_SUB_STRIPPED,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
} else {
@@ -985,19 +987,19 @@ public class PgpKeyOperation {
progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / saveParcel.mAddSubKeys.size()));
SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_NEW, indent,
KeyFormattingUtils.getAlgorithmInfo(add.mAlgorithm, add.mKeySize, add.mCurve) );
KeyFormattingUtils.getAlgorithmInfo(add.getAlgorithm(), add.getKeySize(), add.getCurve()) );
if (isDivertToCard(masterSecretKey)) {
log.add(LogType.MSG_MF_ERROR_DIVERT_NEWSUB, indent +1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (add.mExpiry == null) {
if (add.getExpiry() == null) {
log.add(LogType.MSG_MF_ERROR_NULL_EXPIRY, indent +1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (add.mExpiry > 0L && new Date(add.mExpiry*1000).before(new Date())) {
if (add.getExpiry() > 0L && new Date(add.getExpiry() * 1000).before(new Date())) {
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY, indent +1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
@@ -1022,7 +1024,7 @@ public class PgpKeyOperation {
cryptoInput.getSignatureTime(),
masterPublicKey, masterPrivateKey,
getSignatureGenerator(pKey, cryptoInput, false), keyPair.getPrivateKey(), pKey,
add.mFlags, add.mExpiry);
add.getFlags(), add.getExpiry());
pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
} catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
@@ -1158,31 +1160,31 @@ public class PgpKeyOperation {
progress(R.string.progress_modify_subkeychange, (i - 1) * (100 / saveParcel.mChangeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_CHANGE,
indent, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId);
PGPSecretKey sKey = sKR.getSecretKey(change.getSubKeyId());
if (sKey == null) {
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (change.mDummyStrip || change.mSecurityTokenSerialNo != null) {
if (change.getDummyStrip() || change.getSecurityTokenSerialNo() != null) {
// IT'S DANGEROUS~
// no really, it is. this operation irrevocably removes the private key data from the key
if (change.mDummyStrip) {
if (change.getDummyStrip()) {
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
} else {
// the serial number must be 16 bytes in length
if (change.mSecurityTokenSerialNo.length != 16) {
if (change.getSecurityTokenSerialNo().length != 16) {
log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
log.add(LogType.MSG_MF_KEYTOCARD_FINISH, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(change.mKeyId),
Hex.toHexString(change.mSecurityTokenSerialNo, 8, 6));
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.mSecurityTokenSerialNo);
KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()),
Hex.toHexString(change.getSecurityTokenSerialNo(), 8, 6));
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.getSecurityTokenSerialNo());
}
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
}

View File

@@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.pgp;
import com.google.auto.value.AutoValue;
import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.BCPGOutputStream;
import org.bouncycastle.bcpg.Packet;

View File

@@ -24,6 +24,8 @@ import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.math.ec.ECCurve;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
// 4.3.3.6 Algorithm Attributes
public class ECKeyFormat extends KeyFormat {
@@ -105,7 +107,7 @@ public class ECKeyFormat extends KeyFormat {
throw new IllegalArgumentException("Unsupported curve " + mECCurveOID);
}
keyring.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(algo,
keyring.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(algo,
curve.getFieldSize(), scurve, keyFlags, 0L));
}
}

View File

@@ -18,6 +18,8 @@
package org.sufficientlysecure.keychain.securitytoken;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
// 4.3.3.6 Algorithm Attributes
public class RSAKeyFormat extends KeyFormat {
@@ -85,7 +87,7 @@ public class RSAKeyFormat extends KeyFormat {
}
public void addToSaveKeyringParcel(SaveKeyringParcel keyring, int keyFlags) {
keyring.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
keyring.mAddSubKeys.add(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
mModulusLength, null, keyFlags, 0L));
}
}

View File

@@ -20,7 +20,9 @@ package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Passphrase;
@@ -137,8 +139,8 @@ public class SaveKeyringParcel implements Parcelable {
}
for (SubkeyChange change : mChangeSubKeys) {
if (change.mRecertify || change.mFlags != null || change.mExpiry != null
|| change.mMoveKeyToSecurityToken) {
if (change.getRecertify() || change.getFlags() != null || change.getExpiry() != null
|| change.getMoveKeyToSecurityToken()) {
return false;
}
}
@@ -148,109 +150,84 @@ public class SaveKeyringParcel implements Parcelable {
// performance gain for using Parcelable here would probably be negligible,
// use Serializable instead.
public static class SubkeyAdd implements Serializable {
public Algorithm mAlgorithm;
public Integer mKeySize;
public Curve mCurve;
public int mFlags;
public Long mExpiry;
@AutoValue
public abstract static class SubkeyAdd implements Serializable {
public abstract Algorithm getAlgorithm();
@Nullable
public abstract Integer getKeySize();
@Nullable
public abstract Curve getCurve();
public abstract int getFlags();
@Nullable
public abstract Long getExpiry();
public SubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags, Long expiry) {
mAlgorithm = algorithm;
mKeySize = keySize;
mCurve = curve;
mFlags = flags;
mExpiry = expiry;
}
@Override
public String toString() {
String out = "mAlgorithm: " + mAlgorithm + ", ";
out += "mKeySize: " + mKeySize + ", ";
out += "mCurve: " + mCurve + ", ";
out += "mFlags: " + mFlags;
out += "mExpiry: " + mExpiry;
return out;
public static SubkeyAdd createSubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags,
Long expiry) {
return new AutoValue_SaveKeyringParcel_SubkeyAdd(algorithm, keySize, curve, flags, expiry);
}
}
public static class SubkeyChange implements Serializable {
public final long mKeyId;
public Integer mFlags;
@AutoValue
public abstract static class SubkeyChange implements Serializable {
public abstract long getSubKeyId();
@Nullable
public abstract Integer getFlags();
// this is a long unix timestamp, in seconds (NOT MILLISECONDS!)
public Long mExpiry;
@Nullable
public abstract Long getExpiry();
// if this flag is true, the key will be recertified even if all above
// values are no-ops
public boolean mRecertify;
public abstract boolean getRecertify();
// if this flag is true, the subkey should be changed to a stripped key
public boolean mDummyStrip;
public abstract boolean getDummyStrip();
// if this flag is true, the subkey should be moved to a security token
public boolean mMoveKeyToSecurityToken;
public abstract boolean getMoveKeyToSecurityToken();
// if this is non-null, the subkey will be changed to a divert-to-card
// (security token) key for the given serial number
public byte[] mSecurityTokenSerialNo;
@Nullable
public abstract byte[] getSecurityTokenSerialNo();
public SubkeyChange(long keyId) {
mKeyId = keyId;
public static SubkeyChange createRecertifyChange(long keyId, boolean recertify) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, recertify, false, false, null);
}
public SubkeyChange(long keyId, boolean recertify) {
mKeyId = keyId;
mRecertify = recertify;
public static SubkeyChange createFlagsOrExpiryChange(long keyId, Integer flags, Long expiry) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, flags, expiry, false, false, false, null);
}
public SubkeyChange(long keyId, Integer flags, Long expiry) {
mKeyId = keyId;
mFlags = flags;
mExpiry = expiry;
public static SubkeyChange createStripChange(long keyId) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, false, true, false, null);
}
public SubkeyChange(long keyId, boolean dummyStrip, boolean moveKeyToSecurityToken) {
this(keyId, null, null);
// these flags are mutually exclusive!
if (dummyStrip && moveKeyToSecurityToken) {
throw new AssertionError(
"cannot set strip and moveKeyToSecurityToken" +
" flags at the same time - this is a bug!");
}
mDummyStrip = dummyStrip;
mMoveKeyToSecurityToken = moveKeyToSecurityToken;
public static SubkeyChange createMoveToSecurityTokenChange(long keyId) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, false, false, true, null);
}
@Override
public String toString() {
String out = "mKeyId: " + mKeyId + ", ";
out += "mFlags: " + mFlags + ", ";
out += "mExpiry: " + mExpiry + ", ";
out += "mDummyStrip: " + mDummyStrip + ", ";
out += "mMoveKeyToSecurityToken: " + mMoveKeyToSecurityToken + ", ";
out += "mSecurityTokenSerialNo: [" + (mSecurityTokenSerialNo == null ? 0 : mSecurityTokenSerialNo.length) + " bytes]";
return out;
public static SubkeyChange createSecurityTokenSerialNo(long keyId, byte[] securityTokenSerialNo) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, false, false, false, securityTokenSerialNo);
}
}
public SubkeyChange getSubkeyChange(long keyId) {
for (SubkeyChange subkeyChange : mChangeSubKeys) {
if (subkeyChange.mKeyId == keyId) {
if (subkeyChange.getSubKeyId() == keyId) {
return subkeyChange;
}
}
return null;
}
public SubkeyChange getOrCreateSubkeyChange(long keyId) {
SubkeyChange foundSubkeyChange = getSubkeyChange(keyId);
public void addOrReplaceSubkeyChange(SubkeyChange change) {
SubkeyChange foundSubkeyChange = getSubkeyChange(change.getSubKeyId());
if (foundSubkeyChange != null) {
return foundSubkeyChange;
} else {
// else, create a new one
SubkeyChange newSubkeyChange = new SubkeyChange(keyId);
mChangeSubKeys.add(newSubkeyChange);
return newSubkeyChange;
mChangeSubKeys.remove(foundSubkeyChange);
}
mChangeSubKeys.add(change);
}
public void removeSubkeyChange(SubkeyChange change) {
mChangeSubKeys.remove(change);
}
@SuppressWarnings("unchecked") // we verify the reads against writes in writeToParcel

View File

@@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
import org.sufficientlysecure.keychain.service.UploadKeyringParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
@@ -444,7 +445,7 @@ public class CreateKeyFinalFragment extends Fragment {
try {
while (cursor != null && cursor.moveToNext()) {
long subkeyId = cursor.getLong(0);
changeKeyringParcel.getOrCreateSubkeyChange(subkeyId).mMoveKeyToSecurityToken = true;
changeKeyringParcel.mChangeSubKeys.add(SubkeyChange.createMoveToSecurityTokenChange(subkeyId));
}
} finally {
if (cursor != null) {

View File

@@ -431,15 +431,10 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
}
SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null) {
mSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false));
break;
}
// toggle
change.mDummyStrip = !change.mDummyStrip;
if (change.mDummyStrip && change.mMoveKeyToSecurityToken) {
// User had chosen to divert key, but now wants to strip it instead.
change.mMoveKeyToSecurityToken = false;
if (change == null || !change.getDummyStrip()) {
mSaveKeyringParcel.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId));
} else {
mSaveKeyringParcel.removeSubkeyChange(change);
}
break;
}
@@ -479,19 +474,13 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
break;
}
SubkeyChange change;
change = mSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null) {
mSaveKeyringParcel.mChangeSubKeys.add(
new SubkeyChange(keyId, false, true)
);
SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null || !change.getMoveKeyToSecurityToken()) {
mSaveKeyringParcel.addOrReplaceSubkeyChange(
SubkeyChange.createMoveToSecurityTokenChange(keyId));
break;
}
// toggle
change.mMoveKeyToSecurityToken = !change.mMoveKeyToSecurityToken;
if (change.mMoveKeyToSecurityToken && change.mDummyStrip) {
// User had chosen to strip key, but now wants to divert it.
change.mDummyStrip = false;
} else {
mSaveKeyringParcel.removeSubkeyChange(change);
}
break;
}
@@ -523,9 +512,10 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
public void handleMessage(Message message) {
switch (message.what) {
case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY:
mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry =
(Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
Long expiry = (Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
mSaveKeyringParcel.addOrReplaceSubkeyChange(
SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry));
break;
}
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();

View File

@@ -337,15 +337,10 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
}
SubkeyChange change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null) {
mEditModeSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false));
break;
}
// toggle
change.mDummyStrip = !change.mDummyStrip;
if (change.mDummyStrip && change.mMoveKeyToSecurityToken) {
// User had chosen to divert key, but now wants to strip it instead.
change.mMoveKeyToSecurityToken = false;
if (change == null || !change.getDummyStrip()) {
mEditModeSaveKeyringParcel.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId));
} else {
mEditModeSaveKeyringParcel.removeSubkeyChange(change);
}
break;
}
@@ -385,19 +380,12 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
break;
}
SubkeyChange change;
change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null) {
mEditModeSaveKeyringParcel.mChangeSubKeys.add(
new SubkeyChange(keyId, false, true)
);
break;
}
// toggle
change.mMoveKeyToSecurityToken = !change.mMoveKeyToSecurityToken;
if (change.mMoveKeyToSecurityToken && change.mDummyStrip) {
// User had chosen to strip key, but now wants to divert it.
change.mDummyStrip = false;
SubkeyChange change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null || !change.getMoveKeyToSecurityToken()) {
mEditModeSaveKeyringParcel.addOrReplaceSubkeyChange(
SubkeyChange.createMoveToSecurityTokenChange(keyId));
} else {
mEditModeSaveKeyringParcel.removeSubkeyChange(change);
}
break;
}
@@ -429,9 +417,10 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
public void handleMessage(Message message) {
switch (message.what) {
case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY:
mEditModeSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry =
(Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
Long expiry = (Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
mEditModeSaveKeyringParcel.addOrReplaceSubkeyChange(
SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry));
break;
}
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();

View File

@@ -181,8 +181,8 @@ public class SubkeysAdapter extends CursorAdapter {
? mSaveKeyringParcel.getSubkeyChange(keyId)
: null;
if (change != null && (change.mDummyStrip || change.mMoveKeyToSecurityToken)) {
if (change.mDummyStrip) {
if (change != null && (change.getDummyStrip() || change.getMoveKeyToSecurityToken())) {
if (change.getDummyStrip()) {
algorithmStr.append(", ");
final SpannableString boldStripped = new SpannableString(
context.getString(R.string.key_stripped)
@@ -190,7 +190,7 @@ public class SubkeysAdapter extends CursorAdapter {
boldStripped.setSpan(new StyleSpan(Typeface.BOLD), 0, boldStripped.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
algorithmStr.append(boldStripped);
}
if (change.mMoveKeyToSecurityToken) {
if (change.getMoveKeyToSecurityToken()) {
algorithmStr.append(", ");
final SpannableString boldDivert = new SpannableString(
context.getString(R.string.key_divert)
@@ -253,10 +253,10 @@ public class SubkeysAdapter extends CursorAdapter {
SaveKeyringParcel.SubkeyChange subkeyChange = mSaveKeyringParcel.getSubkeyChange(keyId);
if (subkeyChange != null) {
if (subkeyChange.mExpiry == null || subkeyChange.mExpiry == 0L) {
if (subkeyChange.getExpiry() == null || subkeyChange.getExpiry() == 0L) {
expiryDate = null;
} else {
expiryDate = new Date(subkeyChange.mExpiry * 1000);
expiryDate = new Date(subkeyChange.getExpiry() * 1000);
}
}

View File

@@ -100,9 +100,9 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
String algorithmStr = KeyFormattingUtils.getAlgorithmInfo(
mActivity,
holder.mModel.mAlgorithm,
holder.mModel.mKeySize,
holder.mModel.mCurve
holder.mModel.getAlgorithm(),
holder.mModel.getKeySize(),
holder.mModel.getCurve()
);
boolean isMasterKey = mNewKeyring && position == 0;
@@ -148,8 +148,8 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
holder.vKeyId.setText(R.string.edit_key_new_subkey);
holder.vKeyDetails.setText(algorithmStr);
if (holder.mModel.mExpiry != 0L) {
Date expiryDate = new Date(holder.mModel.mExpiry * 1000);
if (holder.mModel.getExpiry() != 0L) {
Date expiryDate = new Date(holder.mModel.getExpiry() * 1000);
Calendar expiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
expiryCal.setTime(expiryDate);
// convert from UTC to time zone of device
@@ -162,7 +162,7 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
+ getContext().getString(R.string.none));
}
int flags = holder.mModel.mFlags;
int flags = holder.mModel.getFlags();
if ((flags & KeyFlags.CERTIFY_OTHER) > 0) {
holder.vCertifyIcon.setVisibility(View.VISIBLE);
} else {

View File

@@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import org.sufficientlysecure.keychain.util.Choice;
import java.util.ArrayList;
@@ -304,7 +305,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
expiry = selectedCal.getTime().getTime() / 1000;
}
SaveKeyringParcel.SubkeyAdd newSubkey = new SaveKeyringParcel.SubkeyAdd(
SaveKeyringParcel.SubkeyAdd newSubkey = SubkeyAdd.createSubkeyAdd(
algorithm, keySize, curve, flags, expiry
);
mAlgorithmSelectedListener.onAlgorithmSelected(newSubkey);