mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-16 13:55:03 -05:00
support yubikeys in (some) edit key operations
This commit is contained in:
parent
25d89b5550
commit
3b04636f5d
@ -83,7 +83,7 @@ public class CertifyOperation extends BaseOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// certification is always with the master key id, so use that one
|
// certification is always with the master key id, so use that one
|
||||||
String passphrase = parcel.mCryptoInput.getPassphrase();
|
char[] passphrase = parcel.mCryptoInput.getPassphrase();
|
||||||
|
|
||||||
if (!certificationKey.unlock(passphrase)) {
|
if (!certificationKey.unlock(passphrase)) {
|
||||||
log.add(LogType.MSG_CRT_ERROR_UNLOCK, 2);
|
log.add(LogType.MSG_CRT_ERROR_UNLOCK, 2);
|
||||||
@ -103,7 +103,7 @@ public class CertifyOperation extends BaseOperation {
|
|||||||
|
|
||||||
int certifyOk = 0, certifyError = 0, uploadOk = 0, uploadError = 0;
|
int certifyOk = 0, certifyError = 0, uploadOk = 0, uploadError = 0;
|
||||||
|
|
||||||
NfcSignOperationsBuilder allRequiredInput = new NfcSignOperationsBuilder(parcel.getSignatureTime());
|
NfcSignOperationsBuilder allRequiredInput = new NfcSignOperationsBuilder(parcel.mCryptoInput.getSignatureTime());
|
||||||
|
|
||||||
// Work through all requested certifications
|
// Work through all requested certifications
|
||||||
for (CertifyAction action : parcel.mCertifyActions) {
|
for (CertifyAction action : parcel.mCertifyActions) {
|
||||||
@ -127,7 +127,7 @@ public class CertifyOperation extends BaseOperation {
|
|||||||
|
|
||||||
PgpCertifyOperation op = new PgpCertifyOperation();
|
PgpCertifyOperation op = new PgpCertifyOperation();
|
||||||
PgpCertifyResult result = op.certify(certificationKey, publicRing,
|
PgpCertifyResult result = op.certify(certificationKey, publicRing,
|
||||||
log, 2, action, parcel.getSignatureData(), parcel.getSignatureTime());
|
log, 2, action, parcel.getSignatureData(), parcel.mCryptoInput.getSignatureTime());
|
||||||
|
|
||||||
if (!result.success()) {
|
if (!result.success()) {
|
||||||
certifyError += 1;
|
certifyError += 1;
|
||||||
|
@ -21,6 +21,7 @@ import android.content.Context;
|
|||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
|
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||||
import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
|
import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
|
||||||
@ -34,6 +35,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException
|
|||||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||||
|
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||||
|
|
||||||
@ -55,7 +57,7 @@ public class EditKeyOperation extends BaseOperation {
|
|||||||
super(context, providerHelper, progressable, cancelled);
|
super(context, providerHelper, progressable, cancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EditKeyResult execute(SaveKeyringParcel saveParcel, String passphrase) {
|
public OperationResult execute(SaveKeyringParcel saveParcel, CryptoInputParcel cryptoInput) {
|
||||||
|
|
||||||
OperationLog log = new OperationLog();
|
OperationLog log = new OperationLog();
|
||||||
log.add(LogType.MSG_ED, 0);
|
log.add(LogType.MSG_ED, 0);
|
||||||
@ -69,7 +71,7 @@ public class EditKeyOperation extends BaseOperation {
|
|||||||
PgpEditKeyResult modifyResult;
|
PgpEditKeyResult modifyResult;
|
||||||
{
|
{
|
||||||
PgpKeyOperation keyOperations =
|
PgpKeyOperation keyOperations =
|
||||||
new PgpKeyOperation(new ProgressScaler(mProgressable, 10, 60, 100), mCancelled);
|
new PgpKeyOperation(new ProgressScaler(mProgressable, 10, 60, 100), mCancelled, cryptoInput);
|
||||||
|
|
||||||
// If a key id is specified, fetch and edit
|
// If a key id is specified, fetch and edit
|
||||||
if (saveParcel.mMasterKeyId != null) {
|
if (saveParcel.mMasterKeyId != null) {
|
||||||
@ -80,7 +82,10 @@ public class EditKeyOperation extends BaseOperation {
|
|||||||
CanonicalizedSecretKeyRing secRing =
|
CanonicalizedSecretKeyRing secRing =
|
||||||
mProviderHelper.getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId);
|
mProviderHelper.getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId);
|
||||||
|
|
||||||
modifyResult = keyOperations.modifySecretKeyRing(secRing, saveParcel, passphrase);
|
modifyResult = keyOperations.modifySecretKeyRing(secRing, saveParcel);
|
||||||
|
if (modifyResult.isPending()) {
|
||||||
|
return modifyResult;
|
||||||
|
}
|
||||||
|
|
||||||
} catch (NotFoundException e) {
|
} catch (NotFoundException e) {
|
||||||
log.add(LogType.MSG_ED_ERROR_KEY_NOT_FOUND, 2);
|
log.add(LogType.MSG_ED_ERROR_KEY_NOT_FOUND, 2);
|
||||||
|
@ -11,66 +11,35 @@ public class InputPendingResult extends OperationResult {
|
|||||||
// the fourth bit indicates a "data pending" result! (it's also a form of non-success)
|
// the fourth bit indicates a "data pending" result! (it's also a form of non-success)
|
||||||
public static final int RESULT_PENDING = RESULT_ERROR + 8;
|
public static final int RESULT_PENDING = RESULT_ERROR + 8;
|
||||||
|
|
||||||
public static final int RESULT_PENDING_PASSPHRASE = RESULT_PENDING + 16;
|
|
||||||
public static final int RESULT_PENDING_NFC = RESULT_PENDING + 32;
|
|
||||||
|
|
||||||
final RequiredInputParcel mRequiredInput;
|
final RequiredInputParcel mRequiredInput;
|
||||||
final Long mKeyIdPassphraseNeeded;
|
|
||||||
|
|
||||||
public InputPendingResult(int result, OperationLog log) {
|
public InputPendingResult(int result, OperationLog log) {
|
||||||
super(result, log);
|
super(result, log);
|
||||||
mRequiredInput = null;
|
mRequiredInput = null;
|
||||||
mKeyIdPassphraseNeeded = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputPendingResult(OperationLog log, RequiredInputParcel requiredInput) {
|
public InputPendingResult(OperationLog log, RequiredInputParcel requiredInput) {
|
||||||
super(RESULT_PENDING_NFC, log);
|
super(RESULT_PENDING, log);
|
||||||
mRequiredInput = requiredInput;
|
mRequiredInput = requiredInput;
|
||||||
mKeyIdPassphraseNeeded = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputPendingResult(OperationLog log, long keyIdPassphraseNeeded) {
|
|
||||||
super(RESULT_PENDING_PASSPHRASE, log);
|
|
||||||
mRequiredInput = null;
|
|
||||||
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputPendingResult(Parcel source) {
|
public InputPendingResult(Parcel source) {
|
||||||
super(source);
|
super(source);
|
||||||
mRequiredInput = source.readParcelable(getClass().getClassLoader());
|
mRequiredInput = source.readParcelable(getClass().getClassLoader());
|
||||||
mKeyIdPassphraseNeeded = source.readInt() != 0 ? source.readLong() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
super.writeToParcel(dest, flags);
|
super.writeToParcel(dest, flags);
|
||||||
dest.writeParcelable(mRequiredInput, 0);
|
dest.writeParcelable(mRequiredInput, 0);
|
||||||
if (mKeyIdPassphraseNeeded != null) {
|
|
||||||
dest.writeInt(1);
|
|
||||||
dest.writeLong(mKeyIdPassphraseNeeded);
|
|
||||||
} else {
|
|
||||||
dest.writeInt(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPending() {
|
public boolean isPending() {
|
||||||
return (mResult & RESULT_PENDING) == RESULT_PENDING;
|
return (mResult & RESULT_PENDING) == RESULT_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNfcPending() {
|
|
||||||
return (mResult & RESULT_PENDING_NFC) == RESULT_PENDING_NFC;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPassphrasePending() {
|
|
||||||
return (mResult & RESULT_PENDING_PASSPHRASE) == RESULT_PENDING_PASSPHRASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequiredInputParcel getRequiredInputParcel() {
|
public RequiredInputParcel getRequiredInputParcel() {
|
||||||
return mRequiredInput;
|
return mRequiredInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getPassphraseKeyId() {
|
|
||||||
return mKeyIdPassphraseNeeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -512,6 +512,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
|
|
||||||
// secret key modify
|
// secret key modify
|
||||||
MSG_MF (LogLevel.START, R.string.msg_mr),
|
MSG_MF (LogLevel.START, R.string.msg_mr),
|
||||||
|
MSG_MF_DIVERT (LogLevel.DEBUG, R.string.msg_mf_divert),
|
||||||
MSG_MF_ERROR_DIVERT_SERIAL (LogLevel.ERROR, R.string.msg_mf_error_divert_serial),
|
MSG_MF_ERROR_DIVERT_SERIAL (LogLevel.ERROR, R.string.msg_mf_error_divert_serial),
|
||||||
MSG_MF_ERROR_ENCODE (LogLevel.ERROR, R.string.msg_mf_error_encode),
|
MSG_MF_ERROR_ENCODE (LogLevel.ERROR, R.string.msg_mf_error_encode),
|
||||||
MSG_MF_ERROR_FINGERPRINT (LogLevel.ERROR, R.string.msg_mf_error_fingerprint),
|
MSG_MF_ERROR_FINGERPRINT (LogLevel.ERROR, R.string.msg_mf_error_fingerprint),
|
||||||
@ -529,6 +530,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_MF_ERROR_REVOKED_PRIMARY (LogLevel.ERROR, R.string.msg_mf_error_revoked_primary),
|
MSG_MF_ERROR_REVOKED_PRIMARY (LogLevel.ERROR, R.string.msg_mf_error_revoked_primary),
|
||||||
MSG_MF_ERROR_SIG (LogLevel.ERROR, R.string.msg_mf_error_sig),
|
MSG_MF_ERROR_SIG (LogLevel.ERROR, R.string.msg_mf_error_sig),
|
||||||
MSG_MF_ERROR_SUBKEY_MISSING(LogLevel.ERROR, R.string.msg_mf_error_subkey_missing),
|
MSG_MF_ERROR_SUBKEY_MISSING(LogLevel.ERROR, R.string.msg_mf_error_subkey_missing),
|
||||||
|
MSG_MF_INPUT_REQUIRED (LogLevel.OK, R.string.msg_mf_input_required),
|
||||||
MSG_MF_MASTER (LogLevel.DEBUG, R.string.msg_mf_master),
|
MSG_MF_MASTER (LogLevel.DEBUG, R.string.msg_mf_master),
|
||||||
MSG_MF_NOTATION_PIN (LogLevel.DEBUG, R.string.msg_mf_notation_pin),
|
MSG_MF_NOTATION_PIN (LogLevel.DEBUG, R.string.msg_mf_notation_pin),
|
||||||
MSG_MF_NOTATION_EMPTY (LogLevel.DEBUG, R.string.msg_mf_notation_empty),
|
MSG_MF_NOTATION_EMPTY (LogLevel.DEBUG, R.string.msg_mf_notation_empty),
|
||||||
@ -596,7 +598,6 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_PR_SUCCESS (LogLevel.OK, R.string.msg_pr_success),
|
MSG_PR_SUCCESS (LogLevel.OK, R.string.msg_pr_success),
|
||||||
|
|
||||||
// messages used in UI code
|
// messages used in UI code
|
||||||
MSG_EK_ERROR_DIVERT (LogLevel.ERROR, R.string.msg_ek_error_divert),
|
|
||||||
MSG_EK_ERROR_DUMMY (LogLevel.ERROR, R.string.msg_ek_error_dummy),
|
MSG_EK_ERROR_DUMMY (LogLevel.ERROR, R.string.msg_ek_error_dummy),
|
||||||
MSG_EK_ERROR_NOT_FOUND (LogLevel.ERROR, R.string.msg_ek_error_not_found),
|
MSG_EK_ERROR_NOT_FOUND (LogLevel.ERROR, R.string.msg_ek_error_not_found),
|
||||||
|
|
||||||
|
@ -22,8 +22,10 @@ import android.os.Parcel;
|
|||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||||
|
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||||
|
|
||||||
public class PgpEditKeyResult extends OperationResult {
|
|
||||||
|
public class PgpEditKeyResult extends InputPendingResult {
|
||||||
|
|
||||||
private transient UncachedKeyRing mRing;
|
private transient UncachedKeyRing mRing;
|
||||||
public final long mRingMasterKeyId;
|
public final long mRingMasterKeyId;
|
||||||
@ -35,6 +37,11 @@ public class PgpEditKeyResult extends OperationResult {
|
|||||||
mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none;
|
mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PgpEditKeyResult(OperationLog log, RequiredInputParcel requiredInput) {
|
||||||
|
super(log, requiredInput);
|
||||||
|
mRingMasterKeyId = Constants.key.none;
|
||||||
|
}
|
||||||
|
|
||||||
public UncachedKeyRing getRing() {
|
public UncachedKeyRing getRing() {
|
||||||
return mRing;
|
return mRing;
|
||||||
}
|
}
|
||||||
|
@ -149,10 +149,14 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean unlock(String passphrase) throws PgpGeneralException {
|
||||||
|
return unlock(passphrase.toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true on right passphrase
|
* Returns true on right passphrase
|
||||||
*/
|
*/
|
||||||
public boolean unlock(String passphrase) throws PgpGeneralException {
|
public boolean unlock(char[] passphrase) throws PgpGeneralException {
|
||||||
// handle keys on OpenPGP cards like they were unlocked
|
// handle keys on OpenPGP cards like they were unlocked
|
||||||
if (mSecretKey.getS2K() != null
|
if (mSecretKey.getS2K() != null
|
||||||
&& mSecretKey.getS2K().getType() == S2K.GNU_DUMMY_S2K
|
&& mSecretKey.getS2K().getType() == S2K.GNU_DUMMY_S2K
|
||||||
@ -164,7 +168,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
|||||||
// try to extract keys using the passphrase
|
// try to extract keys using the passphrase
|
||||||
try {
|
try {
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase);
|
||||||
mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor);
|
mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor);
|
||||||
mPrivateKeyState = PRIVATE_KEY_STATE_UNLOCKED;
|
mPrivateKeyState = PRIVATE_KEY_STATE_UNLOCKED;
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
import org.spongycastle.bcpg.S2K;
|
||||||
import org.spongycastle.bcpg.sig.Features;
|
import org.spongycastle.bcpg.sig.Features;
|
||||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||||
import org.spongycastle.jce.spec.ElGamalParameterSpec;
|
import org.spongycastle.jce.spec.ElGamalParameterSpec;
|
||||||
@ -36,6 +36,7 @@ import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector;
|
|||||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
|
||||||
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
|
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
|
||||||
|
import org.spongycastle.openpgp.operator.PGPDataDecryptor;
|
||||||
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
|
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
|
||||||
@ -43,6 +44,8 @@ import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBu
|
|||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
|
import org.spongycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
|
||||||
|
import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder;
|
||||||
|
import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
@ -54,6 +57,9 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
|
|||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
|
||||||
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.input.CryptoInputParcel;
|
||||||
|
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||||
|
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
@ -85,9 +91,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
* This indicator may be null.
|
* This indicator may be null.
|
||||||
*/
|
*/
|
||||||
public class PgpKeyOperation {
|
public class PgpKeyOperation {
|
||||||
|
|
||||||
private Stack<Progressable> mProgress;
|
private Stack<Progressable> mProgress;
|
||||||
private AtomicBoolean mCancelled;
|
private AtomicBoolean mCancelled;
|
||||||
|
|
||||||
|
NfcSignOperationsBuilder mNfcSignOps;
|
||||||
|
private CryptoInputParcel mCryptoInput;
|
||||||
|
|
||||||
public PgpKeyOperation(Progressable progress) {
|
public PgpKeyOperation(Progressable progress) {
|
||||||
super();
|
super();
|
||||||
if (progress != null) {
|
if (progress != null) {
|
||||||
@ -96,9 +106,11 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PgpKeyOperation(Progressable progress, AtomicBoolean cancelled) {
|
public PgpKeyOperation(Progressable progress, AtomicBoolean cancelled, CryptoInputParcel cryptoInput) {
|
||||||
this(progress);
|
this(progress);
|
||||||
mCancelled = cancelled;
|
mCancelled = cancelled;
|
||||||
|
mNfcSignOps = new NfcSignOperationsBuilder(cryptoInput.getSignatureTime());
|
||||||
|
mCryptoInput = cryptoInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkCancelled() {
|
private boolean checkCancelled() {
|
||||||
@ -316,7 +328,8 @@ public class PgpKeyOperation {
|
|||||||
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
|
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
|
||||||
|
|
||||||
subProgressPush(50, 100);
|
subProgressPush(50, 100);
|
||||||
return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, "", log);
|
CryptoInputParcel cryptoInput = new CryptoInputParcel(new Date(), "");
|
||||||
|
return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, log);
|
||||||
|
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
|
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
|
||||||
@ -347,8 +360,8 @@ public class PgpKeyOperation {
|
|||||||
* namely stripping of subkeys and changing the protection mode of dummy keys.
|
* namely stripping of subkeys and changing the protection mode of dummy keys.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel,
|
public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR,
|
||||||
String passphrase) {
|
SaveKeyringParcel saveParcel) {
|
||||||
|
|
||||||
OperationLog log = new OperationLog();
|
OperationLog log = new OperationLog();
|
||||||
int indent = 0;
|
int indent = 0;
|
||||||
@ -386,11 +399,16 @@ public class PgpKeyOperation {
|
|||||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have no passphrase, only allow restricted operation
|
if (saveParcel.isRestrictedOnly()) {
|
||||||
if (passphrase == null) {
|
|
||||||
return internalRestricted(sKR, saveParcel, log);
|
return internalRestricted(sKR, saveParcel, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do we require a passphrase? If so, pass it along
|
||||||
|
if (!isDivertToCard(masterSecretKey) && !mCryptoInput.hasPassphrase()) {
|
||||||
|
return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredPassphrase(
|
||||||
|
masterSecretKey.getKeyID(), mCryptoInput.getSignatureTime()));
|
||||||
|
}
|
||||||
|
|
||||||
// read masterKeyFlags, and use the same as before.
|
// read masterKeyFlags, and use the same as before.
|
||||||
// since this is the master key, this contains at least CERTIFY_OTHER
|
// since this is the master key, this contains at least CERTIFY_OTHER
|
||||||
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
|
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
|
||||||
@ -398,13 +416,13 @@ public class PgpKeyOperation {
|
|||||||
Date expiryTime = wsKR.getPublicKey().getExpiryTime();
|
Date expiryTime = wsKR.getPublicKey().getExpiryTime();
|
||||||
long masterKeyExpiry = expiryTime != null ? expiryTime.getTime() / 1000 : 0L;
|
long masterKeyExpiry = expiryTime != null ? expiryTime.getTime() / 1000 : 0L;
|
||||||
|
|
||||||
return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, saveParcel, passphrase, log);
|
return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, saveParcel, log);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
|
private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
|
||||||
int masterKeyFlags, long masterKeyExpiry,
|
int masterKeyFlags, long masterKeyExpiry,
|
||||||
SaveKeyringParcel saveParcel, String passphrase,
|
SaveKeyringParcel saveParcel,
|
||||||
OperationLog log) {
|
OperationLog log) {
|
||||||
|
|
||||||
int indent = 1;
|
int indent = 1;
|
||||||
@ -413,18 +431,25 @@ public class PgpKeyOperation {
|
|||||||
|
|
||||||
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
|
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
|
||||||
|
|
||||||
// 1. Unlock private key
|
|
||||||
progress(R.string.progress_modify_unlock, 10);
|
|
||||||
log.add(LogType.MSG_MF_UNLOCK, indent);
|
|
||||||
PGPPrivateKey masterPrivateKey;
|
PGPPrivateKey masterPrivateKey;
|
||||||
{
|
|
||||||
try {
|
if (isDivertToCard(masterSecretKey)) {
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
masterPrivateKey = null;
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
log.add(LogType.MSG_MF_DIVERT, indent);
|
||||||
masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
|
} else {
|
||||||
} catch (PGPException e) {
|
|
||||||
log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
|
// 1. Unlock private key
|
||||||
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
progress(R.string.progress_modify_unlock, 10);
|
||||||
|
log.add(LogType.MSG_MF_UNLOCK, indent);
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||||
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mCryptoInput.getPassphrase());
|
||||||
|
masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
|
||||||
|
} catch (PGPException e) {
|
||||||
|
log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
|
||||||
|
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,9 +504,16 @@ public class PgpKeyOperation {
|
|||||||
boolean isPrimary = saveParcel.mChangePrimaryUserId != null
|
boolean isPrimary = saveParcel.mChangePrimaryUserId != null
|
||||||
&& userId.equals(saveParcel.mChangePrimaryUserId);
|
&& userId.equals(saveParcel.mChangePrimaryUserId);
|
||||||
// generate and add new certificate
|
// generate and add new certificate
|
||||||
PGPSignature cert = generateUserIdSignature(masterPrivateKey,
|
try {
|
||||||
masterPublicKey, userId, isPrimary, masterKeyFlags, masterKeyExpiry);
|
PGPSignature cert = generateUserIdSignature(
|
||||||
modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
|
getSignatureGenerator(masterSecretKey, mCryptoInput),
|
||||||
|
mCryptoInput.getSignatureTime(),
|
||||||
|
masterPrivateKey, masterPublicKey, userId,
|
||||||
|
isPrimary, masterKeyFlags, masterKeyExpiry);
|
||||||
|
modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
|
||||||
|
} catch (NfcInteractionNeeded e) {
|
||||||
|
mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
subProgressPop();
|
subProgressPop();
|
||||||
|
|
||||||
@ -508,9 +540,15 @@ public class PgpKeyOperation {
|
|||||||
PGPUserAttributeSubpacketVector vector = attribute.getVector();
|
PGPUserAttributeSubpacketVector vector = attribute.getVector();
|
||||||
|
|
||||||
// generate and add new certificate
|
// generate and add new certificate
|
||||||
PGPSignature cert = generateUserAttributeSignature(masterPrivateKey,
|
try {
|
||||||
masterPublicKey, vector);
|
PGPSignature cert = generateUserAttributeSignature(
|
||||||
modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, vector, cert);
|
getSignatureGenerator(masterSecretKey, mCryptoInput),
|
||||||
|
mCryptoInput.getSignatureTime(),
|
||||||
|
masterPrivateKey, masterPublicKey, vector);
|
||||||
|
modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, vector, cert);
|
||||||
|
} catch (NfcInteractionNeeded e) {
|
||||||
|
mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
subProgressPop();
|
subProgressPop();
|
||||||
|
|
||||||
@ -538,9 +576,15 @@ public class PgpKeyOperation {
|
|||||||
|
|
||||||
// a duplicate revocation will be removed during canonicalization, so no need to
|
// a duplicate revocation will be removed during canonicalization, so no need to
|
||||||
// take care of that here.
|
// take care of that here.
|
||||||
PGPSignature cert = generateRevocationSignature(masterPrivateKey,
|
try {
|
||||||
masterPublicKey, userId);
|
PGPSignature cert = generateRevocationSignature(
|
||||||
modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
|
getSignatureGenerator(masterSecretKey, mCryptoInput),
|
||||||
|
mCryptoInput.getSignatureTime(),
|
||||||
|
masterPrivateKey, masterPublicKey, userId);
|
||||||
|
modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
|
||||||
|
} catch (NfcInteractionNeeded e) {
|
||||||
|
mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
subProgressPop();
|
subProgressPop();
|
||||||
|
|
||||||
@ -610,11 +654,18 @@ public class PgpKeyOperation {
|
|||||||
log.add(LogType.MSG_MF_PRIMARY_REPLACE_OLD, indent);
|
log.add(LogType.MSG_MF_PRIMARY_REPLACE_OLD, indent);
|
||||||
modifiedPublicKey = PGPPublicKey.removeCertification(
|
modifiedPublicKey = PGPPublicKey.removeCertification(
|
||||||
modifiedPublicKey, userId, currentCert);
|
modifiedPublicKey, userId, currentCert);
|
||||||
PGPSignature newCert = generateUserIdSignature(
|
try {
|
||||||
masterPrivateKey, masterPublicKey, userId, false,
|
PGPSignature newCert = generateUserIdSignature(
|
||||||
masterKeyFlags, masterKeyExpiry);
|
getSignatureGenerator(masterSecretKey, mCryptoInput),
|
||||||
modifiedPublicKey = PGPPublicKey.addCertification(
|
mCryptoInput.getSignatureTime(),
|
||||||
modifiedPublicKey, userId, newCert);
|
masterPrivateKey, masterPublicKey, userId, false,
|
||||||
|
masterKeyFlags, masterKeyExpiry);
|
||||||
|
modifiedPublicKey = PGPPublicKey.addCertification(
|
||||||
|
modifiedPublicKey, userId, newCert);
|
||||||
|
} catch (NfcInteractionNeeded e) {
|
||||||
|
mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,11 +677,17 @@ public class PgpKeyOperation {
|
|||||||
log.add(LogType.MSG_MF_PRIMARY_NEW, indent);
|
log.add(LogType.MSG_MF_PRIMARY_NEW, indent);
|
||||||
modifiedPublicKey = PGPPublicKey.removeCertification(
|
modifiedPublicKey = PGPPublicKey.removeCertification(
|
||||||
modifiedPublicKey, userId, currentCert);
|
modifiedPublicKey, userId, currentCert);
|
||||||
PGPSignature newCert = generateUserIdSignature(
|
try {
|
||||||
masterPrivateKey, masterPublicKey, userId, true,
|
PGPSignature newCert = generateUserIdSignature(
|
||||||
masterKeyFlags, masterKeyExpiry);
|
getSignatureGenerator(masterSecretKey, mCryptoInput),
|
||||||
modifiedPublicKey = PGPPublicKey.addCertification(
|
mCryptoInput.getSignatureTime(),
|
||||||
modifiedPublicKey, userId, newCert);
|
masterPrivateKey, masterPublicKey, userId, true,
|
||||||
|
masterKeyFlags, masterKeyExpiry);
|
||||||
|
modifiedPublicKey = PGPPublicKey.addCertification(
|
||||||
|
modifiedPublicKey, userId, newCert);
|
||||||
|
} catch (NfcInteractionNeeded e) {
|
||||||
|
mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
|
||||||
|
}
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -717,7 +774,8 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PGPPublicKey pKey =
|
PGPPublicKey pKey =
|
||||||
updateMasterCertificates(masterPrivateKey, masterPublicKey,
|
updateMasterCertificates(
|
||||||
|
masterSecretKey, masterPrivateKey, masterPublicKey,
|
||||||
flags, expiry, indent, log);
|
flags, expiry, indent, log);
|
||||||
if (pKey == null) {
|
if (pKey == null) {
|
||||||
// error log entry has already been added by updateMasterCertificates itself
|
// error log entry has already been added by updateMasterCertificates itself
|
||||||
@ -755,9 +813,16 @@ public class PgpKeyOperation {
|
|||||||
pKey = PGPPublicKey.removeCertification(pKey, sig);
|
pKey = PGPPublicKey.removeCertification(pKey, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||||
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||||
|
mCryptoInput.getPassphrase());
|
||||||
|
PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
|
||||||
|
PGPSignature sig = generateSubkeyBindingSignature(
|
||||||
|
getSignatureGenerator(masterSecretKey, mCryptoInput),
|
||||||
|
mCryptoInput.getSignatureTime(),
|
||||||
|
masterPublicKey, masterPrivateKey, subPrivateKey, pKey, flags, expiry);
|
||||||
|
|
||||||
// generate and add new signature
|
// generate and add new signature
|
||||||
PGPSignature sig = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey,
|
|
||||||
sKey, pKey, flags, expiry, passphrase);
|
|
||||||
pKey = PGPPublicKey.addCertification(pKey, sig);
|
pKey = PGPPublicKey.addCertification(pKey, sig);
|
||||||
sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
|
sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
|
||||||
}
|
}
|
||||||
@ -781,10 +846,17 @@ public class PgpKeyOperation {
|
|||||||
PGPPublicKey pKey = sKey.getPublicKey();
|
PGPPublicKey pKey = sKey.getPublicKey();
|
||||||
|
|
||||||
// generate and add new signature
|
// generate and add new signature
|
||||||
PGPSignature sig = generateRevocationSignature(masterPublicKey, masterPrivateKey, pKey);
|
try {
|
||||||
|
PGPSignature sig = generateRevocationSignature(
|
||||||
|
getSignatureGenerator(masterSecretKey, mCryptoInput),
|
||||||
|
mCryptoInput.getSignatureTime(),
|
||||||
|
masterPublicKey, masterPrivateKey, pKey);
|
||||||
|
|
||||||
pKey = PGPPublicKey.addCertification(pKey, sig);
|
pKey = PGPPublicKey.addCertification(pKey, sig);
|
||||||
sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
|
sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
|
||||||
|
} catch (NfcInteractionNeeded e) {
|
||||||
|
mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
subProgressPop();
|
subProgressPop();
|
||||||
|
|
||||||
@ -827,19 +899,29 @@ public class PgpKeyOperation {
|
|||||||
|
|
||||||
// add subkey binding signature (making this a sub rather than master key)
|
// add subkey binding signature (making this a sub rather than master key)
|
||||||
PGPPublicKey pKey = keyPair.getPublicKey();
|
PGPPublicKey pKey = keyPair.getPublicKey();
|
||||||
PGPSignature cert = generateSubkeyBindingSignature(
|
try {
|
||||||
masterPublicKey, masterPrivateKey, keyPair.getPrivateKey(), pKey,
|
PGPSignature cert = generateSubkeyBindingSignature(
|
||||||
add.mFlags, add.mExpiry);
|
getSignatureGenerator(masterSecretKey, mCryptoInput),
|
||||||
pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
|
mCryptoInput.getSignatureTime(),
|
||||||
|
masterPublicKey, masterPrivateKey, keyPair.getPrivateKey(), pKey,
|
||||||
|
add.mFlags, add.mExpiry);
|
||||||
|
pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
|
||||||
|
} catch (NfcInteractionNeeded e) {
|
||||||
|
mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
|
||||||
|
}
|
||||||
|
|
||||||
PGPSecretKey sKey; {
|
PGPSecretKey sKey; {
|
||||||
|
char[] passphrase = mCryptoInput.getPassphrase();
|
||||||
|
if (passphrase == null) {
|
||||||
|
passphrase = new char[] { };
|
||||||
|
}
|
||||||
// Build key encrypter and decrypter based on passphrase
|
// Build key encrypter and decrypter based on passphrase
|
||||||
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder()
|
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder()
|
||||||
.build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
.build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
||||||
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
||||||
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
||||||
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase);
|
||||||
|
|
||||||
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
|
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
|
||||||
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
|
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
|
||||||
@ -867,7 +949,7 @@ public class PgpKeyOperation {
|
|||||||
indent += 1;
|
indent += 1;
|
||||||
|
|
||||||
sKR = applyNewUnlock(sKR, masterPublicKey, masterPrivateKey,
|
sKR = applyNewUnlock(sKR, masterPublicKey, masterPrivateKey,
|
||||||
passphrase, saveParcel.mNewUnlock, log, indent);
|
mCryptoInput.getPassphrase(), saveParcel.mNewUnlock, 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);
|
||||||
@ -891,6 +973,12 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
progress(R.string.progress_done, 100);
|
progress(R.string.progress_done, 100);
|
||||||
|
|
||||||
|
if (!mNfcSignOps.isEmpty()) {
|
||||||
|
log.add(LogType.MSG_MF_INPUT_REQUIRED, indent);
|
||||||
|
return new PgpEditKeyResult(log, mNfcSignOps.build());
|
||||||
|
}
|
||||||
|
|
||||||
log.add(LogType.MSG_MF_SUCCESS, indent);
|
log.add(LogType.MSG_MF_SUCCESS, indent);
|
||||||
return new PgpEditKeyResult(OperationResult.RESULT_OK, log, new UncachedKeyRing(sKR));
|
return new PgpEditKeyResult(OperationResult.RESULT_OK, log, new UncachedKeyRing(sKR));
|
||||||
|
|
||||||
@ -967,7 +1055,7 @@ public class PgpKeyOperation {
|
|||||||
PGPSecretKeyRing sKR,
|
PGPSecretKeyRing sKR,
|
||||||
PGPPublicKey masterPublicKey,
|
PGPPublicKey masterPublicKey,
|
||||||
PGPPrivateKey masterPrivateKey,
|
PGPPrivateKey masterPrivateKey,
|
||||||
String passphrase,
|
char[] passphrase,
|
||||||
ChangeUnlockParcel newUnlock,
|
ChangeUnlockParcel newUnlock,
|
||||||
OperationLog log, int indent) throws PGPException {
|
OperationLog log, int indent) throws PGPException {
|
||||||
|
|
||||||
@ -1051,14 +1139,14 @@ public class PgpKeyOperation {
|
|||||||
private static PGPSecretKeyRing applyNewPassphrase(
|
private static PGPSecretKeyRing applyNewPassphrase(
|
||||||
PGPSecretKeyRing sKR,
|
PGPSecretKeyRing sKR,
|
||||||
PGPPublicKey masterPublicKey,
|
PGPPublicKey masterPublicKey,
|
||||||
String passphrase,
|
char[] passphrase,
|
||||||
String newPassphrase,
|
String newPassphrase,
|
||||||
OperationLog log, int indent) throws PGPException {
|
OperationLog log, int indent) throws PGPException {
|
||||||
|
|
||||||
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build()
|
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build()
|
||||||
.get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
.get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase);
|
||||||
// Build key encryptor based on new passphrase
|
// Build key encryptor based on new passphrase
|
||||||
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
|
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
|
||||||
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
||||||
@ -1115,8 +1203,9 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Update all (non-revoked) uid signatures with new flags and expiry time. */
|
/** Update all (non-revoked) uid signatures with new flags and expiry time. */
|
||||||
private static PGPPublicKey updateMasterCertificates(
|
private PGPPublicKey updateMasterCertificates(
|
||||||
PGPPrivateKey masterPrivateKey, PGPPublicKey masterPublicKey,
|
PGPSecretKey masterSecretKey, PGPPrivateKey masterPrivateKey,
|
||||||
|
PGPPublicKey masterPublicKey,
|
||||||
int flags, long expiry, int indent, OperationLog log)
|
int flags, long expiry, int indent, OperationLog log)
|
||||||
throws PGPException, IOException, SignatureException {
|
throws PGPException, IOException, SignatureException {
|
||||||
|
|
||||||
@ -1172,10 +1261,16 @@ public class PgpKeyOperation {
|
|||||||
currentCert.getHashedSubPackets().isPrimaryUserID();
|
currentCert.getHashedSubPackets().isPrimaryUserID();
|
||||||
modifiedPublicKey = PGPPublicKey.removeCertification(
|
modifiedPublicKey = PGPPublicKey.removeCertification(
|
||||||
modifiedPublicKey, userId, currentCert);
|
modifiedPublicKey, userId, currentCert);
|
||||||
PGPSignature newCert = generateUserIdSignature(
|
try {
|
||||||
masterPrivateKey, masterPublicKey, userId, isPrimary, flags, expiry);
|
PGPSignature newCert = generateUserIdSignature(
|
||||||
modifiedPublicKey = PGPPublicKey.addCertification(
|
getSignatureGenerator(masterSecretKey, mCryptoInput),
|
||||||
modifiedPublicKey, userId, newCert);
|
mCryptoInput.getSignatureTime(),
|
||||||
|
masterPrivateKey, masterPublicKey, userId, isPrimary, flags, expiry);
|
||||||
|
modifiedPublicKey = PGPPublicKey.addCertification(
|
||||||
|
modifiedPublicKey, userId, newCert);
|
||||||
|
} catch (NfcInteractionNeeded e) {
|
||||||
|
mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
|
||||||
|
}
|
||||||
ok = true;
|
ok = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1190,15 +1285,37 @@ public class PgpKeyOperation {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PGPSignature generateUserIdSignature(
|
private static PGPSignatureGenerator getSignatureGenerator(
|
||||||
|
PGPSecretKey secretKey, CryptoInputParcel cryptoInput) {
|
||||||
|
|
||||||
|
PGPContentSignerBuilder builder;
|
||||||
|
|
||||||
|
S2K s2k = secretKey.getS2K();
|
||||||
|
if (s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K
|
||||||
|
&& s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD) {
|
||||||
|
// use synchronous "NFC based" SignerBuilder
|
||||||
|
builder = new NfcSyncPGPContentSignerBuilder(
|
||||||
|
secretKey.getPublicKey().getAlgorithm(),
|
||||||
|
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO,
|
||||||
|
secretKey.getKeyID(), cryptoInput.getCryptoData())
|
||||||
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
|
} else {
|
||||||
|
// content signer based on signing key algorithm and chosen hash algorithm
|
||||||
|
builder = new JcaPGPContentSignerBuilder(
|
||||||
|
secretKey.getPublicKey().getAlgorithm(),
|
||||||
|
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||||
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PGPSignatureGenerator(builder);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private PGPSignature generateUserIdSignature(
|
||||||
|
PGPSignatureGenerator sGen, Date creationTime,
|
||||||
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId, boolean primary,
|
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId, boolean primary,
|
||||||
int flags, long expiry)
|
int flags, long expiry)
|
||||||
throws IOException, PGPException, SignatureException {
|
throws IOException, PGPException, SignatureException {
|
||||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
|
||||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
|
||||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
|
||||||
|
|
||||||
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||||
{
|
{
|
||||||
@ -1222,7 +1339,7 @@ public class PgpKeyOperation {
|
|||||||
hashedPacketsGen.setPrimaryUserID(false, primary);
|
hashedPacketsGen.setPrimaryUserID(false, primary);
|
||||||
|
|
||||||
/* critical subpackets: we consider those important for a modern pgp implementation */
|
/* critical subpackets: we consider those important for a modern pgp implementation */
|
||||||
hashedPacketsGen.setSignatureCreationTime(true, new Date());
|
hashedPacketsGen.setSignatureCreationTime(true, creationTime);
|
||||||
// Request that senders add the MDC to the message (authenticate unsigned messages)
|
// Request that senders add the MDC to the message (authenticate unsigned messages)
|
||||||
hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION);
|
hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION);
|
||||||
hashedPacketsGen.setKeyFlags(true, flags);
|
hashedPacketsGen.setKeyFlags(true, flags);
|
||||||
@ -1238,19 +1355,15 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static PGPSignature generateUserAttributeSignature(
|
private static PGPSignature generateUserAttributeSignature(
|
||||||
|
PGPSignatureGenerator sGen, Date creationTime,
|
||||||
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey,
|
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey,
|
||||||
PGPUserAttributeSubpacketVector vector)
|
PGPUserAttributeSubpacketVector vector)
|
||||||
throws IOException, PGPException, SignatureException {
|
throws IOException, PGPException, SignatureException {
|
||||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
|
||||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
|
||||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
|
||||||
|
|
||||||
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||||
{
|
{
|
||||||
/* critical subpackets: we consider those important for a modern pgp implementation */
|
/* critical subpackets: we consider those important for a modern pgp implementation */
|
||||||
hashedPacketsGen.setSignatureCreationTime(true, new Date());
|
hashedPacketsGen.setSignatureCreationTime(true, creationTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
sGen.setHashedSubpackets(hashedPacketsGen.generate());
|
sGen.setHashedSubpackets(hashedPacketsGen.generate());
|
||||||
@ -1259,29 +1372,24 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static PGPSignature generateRevocationSignature(
|
private static PGPSignature generateRevocationSignature(
|
||||||
|
PGPSignatureGenerator sGen, Date creationTime,
|
||||||
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId)
|
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId)
|
||||||
|
|
||||||
throws IOException, PGPException, SignatureException {
|
throws IOException, PGPException, SignatureException {
|
||||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
|
||||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
|
|
||||||
PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
|
||||||
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||||
subHashedPacketsGen.setSignatureCreationTime(true, new Date());
|
subHashedPacketsGen.setSignatureCreationTime(true, creationTime);
|
||||||
sGen.setHashedSubpackets(subHashedPacketsGen.generate());
|
sGen.setHashedSubpackets(subHashedPacketsGen.generate());
|
||||||
sGen.init(PGPSignature.CERTIFICATION_REVOCATION, masterPrivateKey);
|
sGen.init(PGPSignature.CERTIFICATION_REVOCATION, masterPrivateKey);
|
||||||
return sGen.generateCertification(userId, pKey);
|
return sGen.generateCertification(userId, pKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PGPSignature generateRevocationSignature(
|
private static PGPSignature generateRevocationSignature(
|
||||||
|
PGPSignatureGenerator sGen, Date creationTime,
|
||||||
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey)
|
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey)
|
||||||
throws IOException, PGPException, SignatureException {
|
throws IOException, PGPException, SignatureException {
|
||||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
|
||||||
masterPublicKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
|
||||||
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||||
subHashedPacketsGen.setSignatureCreationTime(true, new Date());
|
subHashedPacketsGen.setSignatureCreationTime(true, creationTime);
|
||||||
sGen.setHashedSubpackets(subHashedPacketsGen.generate());
|
sGen.setHashedSubpackets(subHashedPacketsGen.generate());
|
||||||
// Generate key revocation or subkey revocation, depending on master/subkey-ness
|
// Generate key revocation or subkey revocation, depending on master/subkey-ness
|
||||||
if (masterPublicKey.getKeyID() == pKey.getKeyID()) {
|
if (masterPublicKey.getKeyID() == pKey.getKeyID()) {
|
||||||
@ -1293,26 +1401,12 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PGPSignature generateSubkeyBindingSignature(
|
|
||||||
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
|
|
||||||
PGPSecretKey sKey, PGPPublicKey pKey, int flags, long expiry, String passphrase)
|
|
||||||
throws IOException, PGPException, SignatureException {
|
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
|
||||||
passphrase.toCharArray());
|
|
||||||
PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
|
|
||||||
return generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, subPrivateKey,
|
|
||||||
pKey, flags, expiry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PGPSignature generateSubkeyBindingSignature(
|
static PGPSignature generateSubkeyBindingSignature(
|
||||||
|
PGPSignatureGenerator sGen, Date creationTime,
|
||||||
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
|
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
|
||||||
PGPPrivateKey subPrivateKey, PGPPublicKey pKey, int flags, long expiry)
|
PGPPrivateKey subPrivateKey, PGPPublicKey pKey, int flags, long expiry)
|
||||||
throws IOException, PGPException, SignatureException {
|
throws IOException, PGPException, SignatureException {
|
||||||
|
|
||||||
// date for signing
|
|
||||||
Date creationTime = new Date();
|
|
||||||
|
|
||||||
PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||||
|
|
||||||
// If this key can sign, we need a primary key binding signature
|
// If this key can sign, we need a primary key binding signature
|
||||||
@ -1323,10 +1417,10 @@ public class PgpKeyOperation {
|
|||||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||||
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
PGPSignatureGenerator subSigGen = new PGPSignatureGenerator(signerBuilder);
|
||||||
sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey);
|
subSigGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey);
|
||||||
sGen.setHashedSubpackets(subHashedPacketsGen.generate());
|
subSigGen.setHashedSubpackets(subHashedPacketsGen.generate());
|
||||||
PGPSignature certification = sGen.generateCertification(masterPublicKey, pKey);
|
PGPSignature certification = subSigGen.generateCertification(masterPublicKey, pKey);
|
||||||
unhashedPacketsGen.setEmbeddedSignature(true, certification);
|
unhashedPacketsGen.setEmbeddedSignature(true, certification);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1341,10 +1435,6 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
|
||||||
masterPublicKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
|
||||||
sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey);
|
sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey);
|
||||||
sGen.setHashedSubpackets(hashedPacketsGen.generate());
|
sGen.setHashedSubpackets(hashedPacketsGen.generate());
|
||||||
sGen.setUnhashedSubpackets(unhashedPacketsGen.generate());
|
sGen.setUnhashedSubpackets(unhashedPacketsGen.generate());
|
||||||
@ -1371,4 +1461,10 @@ public class PgpKeyOperation {
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isDivertToCard(PGPSecretKey secretKey) {
|
||||||
|
S2K s2k = secretKey.getS2K();
|
||||||
|
return s2k.getType() == S2K.GNU_DUMMY_S2K
|
||||||
|
&& s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -76,10 +76,6 @@ public class CertifyActionsParcel implements Parcelable {
|
|||||||
return mCryptoInput.getCryptoData();
|
return mCryptoInput.getCryptoData();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getSignatureTime() {
|
|
||||||
return mCryptoInput.getSignatureTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Creator<CertifyActionsParcel> CREATOR = new Creator<CertifyActionsParcel>() {
|
public static final Creator<CertifyActionsParcel> CREATOR = new Creator<CertifyActionsParcel>() {
|
||||||
public CertifyActionsParcel createFromParcel(final Parcel source) {
|
public CertifyActionsParcel createFromParcel(final Parcel source) {
|
||||||
return new CertifyActionsParcel(source);
|
return new CertifyActionsParcel(source);
|
||||||
|
@ -61,6 +61,7 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
|||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler.MessageStatus;
|
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler.MessageStatus;
|
||||||
|
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||||
import org.sufficientlysecure.keychain.util.FileHelper;
|
import org.sufficientlysecure.keychain.util.FileHelper;
|
||||||
import org.sufficientlysecure.keychain.util.InputData;
|
import org.sufficientlysecure.keychain.util.InputData;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
@ -160,6 +161,7 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
// save keyring
|
// save keyring
|
||||||
public static final String EDIT_KEYRING_PARCEL = "save_parcel";
|
public static final String EDIT_KEYRING_PARCEL = "save_parcel";
|
||||||
public static final String EDIT_KEYRING_PASSPHRASE = "passphrase";
|
public static final String EDIT_KEYRING_PASSPHRASE = "passphrase";
|
||||||
|
public static final String EXTRA_CRYPTO_INPUT = "crypto_input";
|
||||||
|
|
||||||
// delete keyring(s)
|
// delete keyring(s)
|
||||||
public static final String DELETE_KEY_LIST = "delete_list";
|
public static final String DELETE_KEY_LIST = "delete_list";
|
||||||
@ -469,11 +471,11 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
|
|
||||||
// Input
|
// Input
|
||||||
SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL);
|
SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL);
|
||||||
String passphrase = data.getString(EDIT_KEYRING_PASSPHRASE);
|
CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT);
|
||||||
|
|
||||||
// Operation
|
// Operation
|
||||||
EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled);
|
EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled);
|
||||||
EditKeyResult result = op.execute(saveParcel, passphrase);
|
OperationResult result = op.execute(saveParcel, cryptoInput);
|
||||||
|
|
||||||
// Result
|
// Result
|
||||||
sendMessageToHandler(MessageStatus.OKAY, result);
|
sendMessageToHandler(MessageStatus.OKAY, result);
|
||||||
|
@ -81,8 +81,8 @@ public class CryptoInputParcel implements Parcelable {
|
|||||||
return mPassphrase != null;
|
return mPassphrase != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassphrase() {
|
public char[] getPassphrase() {
|
||||||
return mPassphrase;
|
return mPassphrase == null ? null : mPassphrase.toCharArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<CryptoInputParcel> CREATOR = new Creator<CryptoInputParcel>() {
|
public static final Creator<CryptoInputParcel> CREATOR = new Creator<CryptoInputParcel>() {
|
||||||
@ -95,4 +95,19 @@ public class CryptoInputParcel implements Parcelable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append("CryptoInput: { ");
|
||||||
|
b.append(mSignatureTime).append(" ");
|
||||||
|
if (mPassphrase != null) {
|
||||||
|
b.append("passphrase");
|
||||||
|
}
|
||||||
|
if (mCryptoData != null) {
|
||||||
|
b.append(mCryptoData.size());
|
||||||
|
b.append(" hashes ");
|
||||||
|
}
|
||||||
|
b.append("}");
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,13 @@ public class RequiredInputParcel implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Date mSignatureTime;
|
public Date mSignatureTime;
|
||||||
|
|
||||||
public final RequiredInputType mType;
|
public final RequiredInputType mType;
|
||||||
|
|
||||||
|
public String mNfcPin = "123456";
|
||||||
public final byte[][] mInputHashes;
|
public final byte[][] mInputHashes;
|
||||||
public final int[] mSignAlgos;
|
public final int[] mSignAlgos;
|
||||||
|
|
||||||
private Long mSubKeyId;
|
private Long mSubKeyId;
|
||||||
|
|
||||||
private RequiredInputParcel(RequiredInputType type, byte[][] inputHashes,
|
private RequiredInputParcel(RequiredInputType type, byte[][] inputHashes,
|
||||||
|
@ -9,6 +9,7 @@ import android.support.v4.app.Fragment;
|
|||||||
|
|
||||||
import org.sufficientlysecure.keychain.operations.results.CertifyResult;
|
import org.sufficientlysecure.keychain.operations.results.CertifyResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.InputPendingResult;
|
import org.sufficientlysecure.keychain.operations.results.InputPendingResult;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler.MessageStatus;
|
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler.MessageStatus;
|
||||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||||
@ -25,7 +26,6 @@ public abstract class CryptoOperationFragment extends Fragment {
|
|||||||
case NFC_DECRYPT:
|
case NFC_DECRYPT:
|
||||||
case NFC_SIGN: {
|
case NFC_SIGN: {
|
||||||
Intent intent = new Intent(getActivity(), NfcOperationActivity.class);
|
Intent intent = new Intent(getActivity(), NfcOperationActivity.class);
|
||||||
intent.putExtra(NfcOperationActivity.EXTRA_PIN, "123456");
|
|
||||||
intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, requiredInput);
|
intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, requiredInput);
|
||||||
startActivityForResult(intent, REQUEST_CODE_NFC);
|
startActivityForResult(intent, REQUEST_CODE_NFC);
|
||||||
return;
|
return;
|
||||||
@ -76,10 +76,14 @@ public abstract class CryptoOperationFragment extends Fragment {
|
|||||||
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
|
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
|
||||||
Bundle data = message.getData();
|
Bundle data = message.getData();
|
||||||
|
|
||||||
InputPendingResult result = data.getParcelable(CertifyResult.EXTRA_RESULT);
|
OperationResult result = data.getParcelable(CertifyResult.EXTRA_RESULT);
|
||||||
|
if (result == null || ! (result instanceof InputPendingResult)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (result != null && result.isPending()) {
|
InputPendingResult pendingResult = (InputPendingResult) result;
|
||||||
RequiredInputParcel requiredInput = result.getRequiredInputParcel();
|
if (pendingResult.isPending()) {
|
||||||
|
RequiredInputParcel requiredInput = pendingResult.getRequiredInputParcel();
|
||||||
initiateInputActivity(requiredInput);
|
initiateInputActivity(requiredInput);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -51,10 +53,10 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
|||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
|
||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
|
||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
|
||||||
|
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
|
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
|
||||||
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter;
|
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter;
|
||||||
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
|
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
|
||||||
@ -68,14 +70,12 @@ import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
|
|||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
public class EditKeyFragment extends LoaderFragment implements
|
public class EditKeyFragment extends CryptoOperationFragment implements
|
||||||
LoaderManager.LoaderCallbacks<Cursor> {
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
public static final String ARG_DATA_URI = "uri";
|
public static final String ARG_DATA_URI = "uri";
|
||||||
public static final String ARG_SAVE_KEYRING_PARCEL = "save_keyring_parcel";
|
public static final String ARG_SAVE_KEYRING_PARCEL = "save_keyring_parcel";
|
||||||
|
|
||||||
public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
|
|
||||||
|
|
||||||
private ListView mUserIdsList;
|
private ListView mUserIdsList;
|
||||||
private ListView mSubkeysList;
|
private ListView mSubkeysList;
|
||||||
private ListView mUserIdsAddedList;
|
private ListView mUserIdsAddedList;
|
||||||
@ -100,7 +100,6 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
private SaveKeyringParcel mSaveKeyringParcel;
|
private SaveKeyringParcel mSaveKeyringParcel;
|
||||||
|
|
||||||
private String mPrimaryUserId;
|
private String mPrimaryUserId;
|
||||||
private String mCurrentPassphrase;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of this fragment
|
* Creates new instance of this fragment
|
||||||
@ -129,8 +128,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
|
||||||
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
|
View view = inflater.inflate(R.layout.edit_key_fragment, null);
|
||||||
View view = inflater.inflate(R.layout.edit_key_fragment, getContainer());
|
|
||||||
|
|
||||||
mUserIdsList = (ListView) view.findViewById(R.id.edit_key_user_ids);
|
mUserIdsList = (ListView) view.findViewById(R.id.edit_key_user_ids);
|
||||||
mSubkeysList = (ListView) view.findViewById(R.id.edit_key_keys);
|
mSubkeysList = (ListView) view.findViewById(R.id.edit_key_keys);
|
||||||
@ -140,7 +138,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
mAddUserId = view.findViewById(R.id.edit_key_action_add_user_id);
|
mAddUserId = view.findViewById(R.id.edit_key_action_add_user_id);
|
||||||
mAddSubkey = view.findViewById(R.id.edit_key_action_add_key);
|
mAddSubkey = view.findViewById(R.id.edit_key_action_add_key);
|
||||||
|
|
||||||
return root;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -155,7 +153,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
if (mDataUri == null) {
|
if (mDataUri == null) {
|
||||||
returnKeyringParcel();
|
returnKeyringParcel();
|
||||||
} else {
|
} else {
|
||||||
saveInDatabase(mCurrentPassphrase);
|
cryptoOperation(new CryptoInputParcel(new Date()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, new OnClickListener() {
|
}, new OnClickListener() {
|
||||||
@ -185,18 +183,12 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
private void loadSaveKeyringParcel(SaveKeyringParcel saveKeyringParcel) {
|
private void loadSaveKeyringParcel(SaveKeyringParcel saveKeyringParcel) {
|
||||||
mSaveKeyringParcel = saveKeyringParcel;
|
mSaveKeyringParcel = saveKeyringParcel;
|
||||||
mPrimaryUserId = saveKeyringParcel.mChangePrimaryUserId;
|
mPrimaryUserId = saveKeyringParcel.mChangePrimaryUserId;
|
||||||
if (saveKeyringParcel.mNewUnlock != null) {
|
|
||||||
mCurrentPassphrase = saveKeyringParcel.mNewUnlock.mNewPassphrase;
|
|
||||||
}
|
|
||||||
|
|
||||||
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, true);
|
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, true);
|
||||||
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
|
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
|
||||||
|
|
||||||
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys, true);
|
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys, true);
|
||||||
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
|
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
|
||||||
|
|
||||||
// show directly
|
|
||||||
setContentShown(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadData(Uri dataUri) {
|
private void loadData(Uri dataUri) {
|
||||||
@ -216,9 +208,6 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
case GNU_DUMMY:
|
case GNU_DUMMY:
|
||||||
finishWithError(LogType.MSG_EK_ERROR_DUMMY);
|
finishWithError(LogType.MSG_EK_ERROR_DUMMY);
|
||||||
return;
|
return;
|
||||||
case DIVERT_TO_CARD:
|
|
||||||
finishWithError(LogType.MSG_EK_ERROR_DIVERT);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
|
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
|
||||||
@ -229,24 +218,10 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Prepare the loaders. Either re-connect with an existing ones,
|
||||||
mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(getActivity(),
|
// or start new ones.
|
||||||
mSaveKeyringParcel.mMasterKeyId, mSaveKeyringParcel.mMasterKeyId);
|
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditKeyFragment.this);
|
||||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this);
|
||||||
finishWithError(LogType.MSG_EK_ERROR_NOT_FOUND);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCurrentPassphrase == null) {
|
|
||||||
Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
|
|
||||||
intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, mSaveKeyringParcel.mMasterKeyId);
|
|
||||||
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
|
|
||||||
} else {
|
|
||||||
// Prepare the loaders. Either re-connect with an existing ones,
|
|
||||||
// or start new ones.
|
|
||||||
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditKeyFragment.this);
|
|
||||||
getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this);
|
|
||||||
}
|
|
||||||
|
|
||||||
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, mSaveKeyringParcel);
|
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, mSaveKeyringParcel);
|
||||||
mUserIdsList.setAdapter(mUserIdsAdapter);
|
mUserIdsList.setAdapter(mUserIdsAdapter);
|
||||||
@ -262,28 +237,6 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
|
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
||||||
switch (requestCode) {
|
|
||||||
case REQUEST_CODE_PASSPHRASE: {
|
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
|
||||||
mCurrentPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
|
||||||
// Prepare the loaders. Either re-connect with an existing ones,
|
|
||||||
// or start new ones.
|
|
||||||
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditKeyFragment.this);
|
|
||||||
getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this);
|
|
||||||
} else {
|
|
||||||
getActivity().finish();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initView() {
|
private void initView() {
|
||||||
mChangePassphrase.setOnClickListener(new View.OnClickListener() {
|
mChangePassphrase.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -322,7 +275,6 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||||
setContentShown(false);
|
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case LOADER_ID_USER_IDS: {
|
case LOADER_ID_USER_IDS: {
|
||||||
@ -355,7 +307,6 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
setContentShown(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -397,7 +348,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
Messenger messenger = new Messenger(returnHandler);
|
Messenger messenger = new Messenger(returnHandler);
|
||||||
|
|
||||||
SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance(
|
SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance(
|
||||||
messenger, mCurrentPassphrase, R.string.title_change_passphrase);
|
messenger, R.string.title_change_passphrase);
|
||||||
|
|
||||||
setPassphraseDialog.show(getActivity().getSupportFragmentManager(), "setPassphraseDialog");
|
setPassphraseDialog.show(getActivity().getSupportFragmentManager(), "setPassphraseDialog");
|
||||||
}
|
}
|
||||||
@ -593,8 +544,11 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveInDatabase(String passphrase) {
|
@Override
|
||||||
Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString());
|
protected void cryptoOperation(CryptoInputParcel cryptoInput) {
|
||||||
|
|
||||||
|
Log.d(Constants.TAG, "cryptoInput:\n" + cryptoInput);
|
||||||
|
Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel);
|
||||||
|
|
||||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
||||||
getActivity(),
|
getActivity(),
|
||||||
@ -605,6 +559,10 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
// handle messages by standard KeychainIntentServiceHandler first
|
// handle messages by standard KeychainIntentServiceHandler first
|
||||||
super.handleMessage(message);
|
super.handleMessage(message);
|
||||||
|
|
||||||
|
if (handlePendingMessage(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
|
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
|
||||||
|
|
||||||
// get returned data bundle
|
// get returned data bundle
|
||||||
@ -640,7 +598,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
|
|
||||||
// fill values for this action
|
// fill values for this action
|
||||||
Bundle data = new Bundle();
|
Bundle data = new Bundle();
|
||||||
data.putString(KeychainIntentService.EDIT_KEYRING_PASSPHRASE, passphrase);
|
data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
|
||||||
data.putParcelable(KeychainIntentService.EDIT_KEYRING_PARCEL, mSaveKeyringParcel);
|
data.putParcelable(KeychainIntentService.EDIT_KEYRING_PARCEL, mSaveKeyringParcel);
|
||||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||||
|
|
||||||
|
@ -62,10 +62,9 @@ public abstract class EncryptActivity extends BaseActivity {
|
|||||||
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
|
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startNfcSign(long keyId, String pin, RequiredInputParcel nfcOps) {
|
protected void startNfcSign(long keyId, RequiredInputParcel nfcOps) {
|
||||||
|
|
||||||
Intent intent = new Intent(this, NfcOperationActivity.class);
|
Intent intent = new Intent(this, NfcOperationActivity.class);
|
||||||
intent.putExtra(NfcOperationActivity.EXTRA_PIN, pin);
|
|
||||||
intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, nfcOps);
|
intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, nfcOps);
|
||||||
// TODO respect keyid(?)
|
// TODO respect keyid(?)
|
||||||
|
|
||||||
@ -148,8 +147,7 @@ public abstract class EncryptActivity extends BaseActivity {
|
|||||||
pgpResult.getNfcHash(),
|
pgpResult.getNfcHash(),
|
||||||
pgpResult.getNfcAlgo(),
|
pgpResult.getNfcAlgo(),
|
||||||
input.getSignatureTime());
|
input.getSignatureTime());
|
||||||
startNfcSign(pgpResult.getNfcKeyId(),
|
startNfcSign(pgpResult.getNfcKeyId(), parcel);
|
||||||
pgpResult.getNfcPassphrase(), parcel);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Unhandled pending result!");
|
throw new RuntimeException("Unhandled pending result!");
|
||||||
|
@ -40,7 +40,6 @@ import java.nio.ByteBuffer;
|
|||||||
@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
|
@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
|
||||||
public class NfcOperationActivity extends BaseActivity {
|
public class NfcOperationActivity extends BaseActivity {
|
||||||
|
|
||||||
public static final String EXTRA_PIN = "pin";
|
|
||||||
public static final String EXTRA_REQUIRED_INPUT = "required_input";
|
public static final String EXTRA_REQUIRED_INPUT = "required_input";
|
||||||
|
|
||||||
public static final String RESULT_DATA = "result_data";
|
public static final String RESULT_DATA = "result_data";
|
||||||
@ -50,8 +49,6 @@ public class NfcOperationActivity extends BaseActivity {
|
|||||||
private NfcAdapter mNfcAdapter;
|
private NfcAdapter mNfcAdapter;
|
||||||
private IsoDep mIsoDep;
|
private IsoDep mIsoDep;
|
||||||
|
|
||||||
private String mPin;
|
|
||||||
|
|
||||||
RequiredInputParcel mNfcOperations;
|
RequiredInputParcel mNfcOperations;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -70,7 +67,6 @@ public class NfcOperationActivity extends BaseActivity {
|
|||||||
Bundle data = intent.getExtras();
|
Bundle data = intent.getExtras();
|
||||||
|
|
||||||
mNfcOperations = data.getParcelable(EXTRA_REQUIRED_INPUT);
|
mNfcOperations = data.getParcelable(EXTRA_REQUIRED_INPUT);
|
||||||
mPin = data.getString(EXTRA_PIN);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,14 +157,16 @@ public class NfcOperationActivity extends BaseActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String pin = mNfcOperations.mNfcPin;
|
||||||
|
|
||||||
// Command APDU for VERIFY command (page 32)
|
// Command APDU for VERIFY command (page 32)
|
||||||
String login =
|
String login =
|
||||||
"00" // CLA
|
"00" // CLA
|
||||||
+ "20" // INS
|
+ "20" // INS
|
||||||
+ "00" // P1
|
+ "00" // P1
|
||||||
+ "82" // P2 (PW1)
|
+ "82" // P2 (PW1)
|
||||||
+ String.format("%02x", mPin.length()) // Lc
|
+ String.format("%02x", pin.length()) // Lc
|
||||||
+ Hex.toHexString(mPin.getBytes());
|
+ Hex.toHexString(pin.getBytes());
|
||||||
if ( ! card(login).equals(accepted)) { // login
|
if ( ! card(login).equals(accepted)) { // login
|
||||||
toast("Wrong PIN!");
|
toast("Wrong PIN!");
|
||||||
setResult(RESULT_CANCELED);
|
setResult(RESULT_CANCELED);
|
||||||
|
@ -49,7 +49,6 @@ import org.sufficientlysecure.keychain.util.Log;
|
|||||||
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
||||||
private static final String ARG_MESSENGER = "messenger";
|
private static final String ARG_MESSENGER = "messenger";
|
||||||
private static final String ARG_TITLE = "title";
|
private static final String ARG_TITLE = "title";
|
||||||
private static final String ARG_OLD_PASSPHRASE = "old_passphrase";
|
|
||||||
|
|
||||||
public static final int MESSAGE_OKAY = 1;
|
public static final int MESSAGE_OKAY = 1;
|
||||||
|
|
||||||
@ -67,12 +66,11 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
* @param messenger to communicate back after setting the passphrase
|
* @param messenger to communicate back after setting the passphrase
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static SetPassphraseDialogFragment newInstance(Messenger messenger, String oldPassphrase, int title) {
|
public static SetPassphraseDialogFragment newInstance(Messenger messenger, int title) {
|
||||||
SetPassphraseDialogFragment frag = new SetPassphraseDialogFragment();
|
SetPassphraseDialogFragment frag = new SetPassphraseDialogFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putInt(ARG_TITLE, title);
|
args.putInt(ARG_TITLE, title);
|
||||||
args.putParcelable(ARG_MESSENGER, messenger);
|
args.putParcelable(ARG_MESSENGER, messenger);
|
||||||
args.putString(ARG_OLD_PASSPHRASE, oldPassphrase);
|
|
||||||
|
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
|
|
||||||
@ -88,7 +86,6 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
|
|
||||||
int title = getArguments().getInt(ARG_TITLE);
|
int title = getArguments().getInt(ARG_TITLE);
|
||||||
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
||||||
String oldPassphrase = getArguments().getString(ARG_OLD_PASSPHRASE);
|
|
||||||
|
|
||||||
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
|
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
|
||||||
|
|
||||||
@ -102,13 +99,6 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
|
mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
|
||||||
mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase);
|
mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase);
|
||||||
|
|
||||||
|
|
||||||
if (TextUtils.isEmpty(oldPassphrase)) {
|
|
||||||
mNoPassphraseCheckBox.setChecked(true);
|
|
||||||
mPassphraseEditText.setEnabled(false);
|
|
||||||
mPassphraseAgainEditText.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
mNoPassphraseCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
mNoPassphraseCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
@ -897,6 +897,7 @@
|
|||||||
|
|
||||||
<!-- modifySecretKeyRing -->
|
<!-- modifySecretKeyRing -->
|
||||||
<string name="msg_mr">"Modifying keyring %s"</string>
|
<string name="msg_mr">"Modifying keyring %s"</string>
|
||||||
|
<string name="msg_mf_divert">"Will divert to card/nfc for crypto operations"</string>
|
||||||
<string name="msg_mf_error_divert_serial">"The serial number of a divert-to-card key must be 16 bytes! This is a programming error, please file a bug report!"</string>
|
<string name="msg_mf_error_divert_serial">"The serial number of a divert-to-card key must be 16 bytes! This is a programming error, please file a bug report!"</string>
|
||||||
<string name="msg_mf_error_encode">"Encoding exception!"</string>
|
<string name="msg_mf_error_encode">"Encoding exception!"</string>
|
||||||
<string name="msg_mf_error_fingerprint">"Actual key fingerprint does not match the expected one!"</string>
|
<string name="msg_mf_error_fingerprint">"Actual key fingerprint does not match the expected one!"</string>
|
||||||
@ -911,6 +912,7 @@
|
|||||||
<string name="msg_mf_error_passphrase_master">"Fatal error decrypting master key! This is likely a programming error, please file a bug report!"</string>
|
<string name="msg_mf_error_passphrase_master">"Fatal error decrypting master key! This is likely a programming error, please file a bug report!"</string>
|
||||||
<string name="msg_mf_error_pgp">"Internal OpenPGP error!"</string>
|
<string name="msg_mf_error_pgp">"Internal OpenPGP error!"</string>
|
||||||
<string name="msg_mf_error_sig">"Signature exception!"</string>
|
<string name="msg_mf_error_sig">"Signature exception!"</string>
|
||||||
|
<string name="msg_mf_input_required">"Diverting to card/nfc for crypto operations"</string>
|
||||||
<string name="msg_mf_master">"Modifying master certifications"</string>
|
<string name="msg_mf_master">"Modifying master certifications"</string>
|
||||||
<string name="msg_mf_notation_empty">"Adding empty notation packet"</string>
|
<string name="msg_mf_notation_empty">"Adding empty notation packet"</string>
|
||||||
<string name="msg_mf_notation_pin">"Adding PIN notation packet"</string>
|
<string name="msg_mf_notation_pin">"Adding PIN notation packet"</string>
|
||||||
@ -987,7 +989,6 @@
|
|||||||
<string name="msg_pr_success">"Key successfully promoted"</string>
|
<string name="msg_pr_success">"Key successfully promoted"</string>
|
||||||
|
|
||||||
<!-- Other messages used in OperationLogs -->
|
<!-- Other messages used in OperationLogs -->
|
||||||
<string name="msg_ek_error_divert">"Editing of NFC keys is not (yet) supported!"</string>
|
|
||||||
<string name="msg_ek_error_dummy">"Cannot edit keyring with stripped master key!"</string>
|
<string name="msg_ek_error_dummy">"Cannot edit keyring with stripped master key!"</string>
|
||||||
<string name="msg_ek_error_not_found">"Key not found!"</string>
|
<string name="msg_ek_error_not_found">"Key not found!"</string>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user