aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java170
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java148
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java306
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java)141
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java53
6 files changed, 496 insertions, 334 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
index 6ce77394c..715d5af30 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
@@ -43,10 +43,13 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+
/**
* Wrapper for a PGPSecretKey.
@@ -184,13 +187,13 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
return PgpConstants.sPreferredHashAlgorithms;
}
- private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo, byte[] nfcSignedHash,
- Date nfcCreationTimestamp) {
+ private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo,
+ Map<ByteBuffer,byte[]> signedHashes) {
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {
// use synchronous "NFC based" SignerBuilder
return new NfcSyncPGPContentSignerBuilder(
mSecretKey.getPublicKey().getAlgorithm(), hashAlgo,
- mSecretKey.getKeyID(), nfcSignedHash, nfcCreationTimestamp)
+ mSecretKey.getKeyID(), signedHashes)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
} else {
// content signer based on signing key algorithm and chosen hash algorithm
@@ -200,29 +203,43 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
}
}
- public PGPSignatureGenerator getSignatureGenerator(int hashAlgo, boolean cleartext,
- byte[] nfcSignedHash, Date nfcCreationTimestamp)
- throws PgpGeneralException {
+ public PGPSignatureGenerator getCertSignatureGenerator(Map<ByteBuffer, byte[]> signedHashes) {
+ PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
+ PgpConstants.CERTIFY_HASH_ALGO, signedHashes);
+
if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
throw new PrivateKeyNotUnlockedException();
}
- if (nfcSignedHash != null && nfcCreationTimestamp == null) {
- throw new PgpGeneralException("Got nfc hash without timestamp!!");
+
+ PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
+ try {
+ signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey);
+ return signatureGenerator;
+ } catch (PGPException e) {
+ Log.e(Constants.TAG, "signing error", e);
+ return null;
+ }
+ }
+
+ public PGPSignatureGenerator getDataSignatureGenerator(int hashAlgo, boolean cleartext,
+ Map<ByteBuffer, byte[]> signedHashes, Date creationTimestamp)
+ throws PgpGeneralException {
+ if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
+ throw new PrivateKeyNotUnlockedException();
}
// We explicitly create a signature creation timestamp in this place.
// That way, we can inject an artificial one from outside, ie the one
// used in previous runs of this function.
- if (nfcCreationTimestamp == null) {
+ if (creationTimestamp == null) {
// to sign using nfc PgpSignEncrypt is executed two times.
// the first time it stops to return the PendingIntent for nfc connection and signing the hash
// the second time the signed hash is used.
// to get the same hash we cache the timestamp for the second round!
- nfcCreationTimestamp = new Date();
+ creationTimestamp = new Date();
}
- PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(hashAlgo,
- nfcSignedHash, nfcCreationTimestamp);
+ PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(hashAlgo, signedHashes);
int signatureType;
if (cleartext) {
@@ -238,7 +255,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, mRing.getPrimaryUserIdWithFallback());
- spGen.setSignatureCreationTime(false, nfcCreationTimestamp);
+ spGen.setSignatureCreationTime(false, creationTimestamp);
signatureGenerator.setHashedSubpackets(spGen.generate());
return signatureGenerator;
} catch (PgpKeyNotFoundException | PGPException e) {
@@ -261,133 +278,6 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
}
}
- /**
- * Certify the given pubkeyid with the given masterkeyid.
- *
- * @param publicKeyRing Keyring to add certification to.
- * @param userIds User IDs to certify
- * @return A keyring with added certifications
- */
- public UncachedKeyRing certifyUserIds(CanonicalizedPublicKeyRing publicKeyRing, List<String> userIds,
- byte[] nfcSignedHash, Date nfcCreationTimestamp) {
- if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
- throw new PrivateKeyNotUnlockedException();
- }
- if (!isMasterKey()) {
- throw new AssertionError("tried to certify with non-master key, this is a programming error!");
- }
- if (publicKeyRing.getMasterKeyId() == getKeyId()) {
- throw new AssertionError("key tried to self-certify, this is a programming error!");
- }
-
- // create a signatureGenerator from the supplied masterKeyId and passphrase
- PGPSignatureGenerator signatureGenerator;
- {
- PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
- PgpConstants.CERTIFY_HASH_ALGO, nfcSignedHash, nfcCreationTimestamp);
-
- signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
- try {
- signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey);
- } catch (PGPException e) {
- Log.e(Constants.TAG, "signing error", e);
- return null;
- }
- }
-
- { // supply signatureGenerator with a SubpacketVector
- PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
- if (nfcCreationTimestamp != null) {
- spGen.setSignatureCreationTime(false, nfcCreationTimestamp);
- Log.d(Constants.TAG, "For NFC: set sig creation time to " + nfcCreationTimestamp);
- }
- PGPSignatureSubpacketVector packetVector = spGen.generate();
- signatureGenerator.setHashedSubpackets(packetVector);
- }
-
- // get the master subkey (which we certify for)
- PGPPublicKey publicKey = publicKeyRing.getPublicKey().getPublicKey();
-
- // fetch public key ring, add the certification and return it
- try {
- for (String userId : userIds) {
- PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
- publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
- }
- } catch (PGPException e) {
- Log.e(Constants.TAG, "signing error", e);
- return null;
- }
-
- PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey);
-
- return new UncachedKeyRing(ring);
- }
-
- /**
- * Certify the given user attributes with the given masterkeyid.
- *
- * @param publicKeyRing Keyring to add certification to.
- * @param userAttributes User IDs to certify, or all if null
- * @return A keyring with added certifications
- */
- public UncachedKeyRing certifyUserAttributes(CanonicalizedPublicKeyRing publicKeyRing,
- List<WrappedUserAttribute> userAttributes, byte[] nfcSignedHash, Date nfcCreationTimestamp) {
- if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
- throw new PrivateKeyNotUnlockedException();
- }
- if (!isMasterKey()) {
- throw new AssertionError("tried to certify with non-master key, this is a programming error!");
- }
- if (publicKeyRing.getMasterKeyId() == getKeyId()) {
- throw new AssertionError("key tried to self-certify, this is a programming error!");
- }
-
- // create a signatureGenerator from the supplied masterKeyId and passphrase
- PGPSignatureGenerator signatureGenerator;
- {
- PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
- PgpConstants.CERTIFY_HASH_ALGO, nfcSignedHash, nfcCreationTimestamp);
-
- signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
- try {
- signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey);
- } catch (PGPException e) {
- Log.e(Constants.TAG, "signing error", e);
- return null;
- }
- }
-
- { // supply signatureGenerator with a SubpacketVector
- PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
- if (nfcCreationTimestamp != null) {
- spGen.setSignatureCreationTime(false, nfcCreationTimestamp);
- Log.d(Constants.TAG, "For NFC: set sig creation time to " + nfcCreationTimestamp);
- }
- PGPSignatureSubpacketVector packetVector = spGen.generate();
- signatureGenerator.setHashedSubpackets(packetVector);
- }
-
- // get the master subkey (which we certify for)
- PGPPublicKey publicKey = publicKeyRing.getPublicKey().getPublicKey();
-
- // fetch public key ring, add the certification and return it
- try {
- for (WrappedUserAttribute userAttribute : userAttributes) {
- PGPUserAttributeSubpacketVector vector = userAttribute.getVector();
- PGPSignature sig = signatureGenerator.generateCertification(vector, publicKey);
- publicKey = PGPPublicKey.addCertification(publicKey, vector, sig);
- }
- } catch (PGPException e) {
- Log.e(Constants.TAG, "signing error", e);
- return null;
- }
-
- PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey);
-
- return new UncachedKeyRing(ring);
- }
-
static class PrivateKeyNotUnlockedException extends RuntimeException {
// this exception is a programming error which happens when an operation which requires
// the private key is called without a previous call to unlock()
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java
new file mode 100644
index 000000000..ff162775a
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java
@@ -0,0 +1,148 @@
+package org.sufficientlysecure.keychain.pgp;
+
+
+import java.nio.ByteBuffer;
+import java.util.Date;
+import java.util.Map;
+
+import org.spongycastle.openpgp.PGPException;
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.spongycastle.openpgp.PGPSignature;
+import org.spongycastle.openpgp.PGPSignatureGenerator;
+import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
+import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
+import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector;
+import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
+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.util.Log;
+
+
+public class PgpCertifyOperation {
+
+ public PgpCertifyResult certify(
+ CanonicalizedSecretKey secretKey,
+ CanonicalizedPublicKeyRing publicRing,
+ OperationLog log,
+ int indent,
+ CertifyAction action,
+ Map<ByteBuffer,byte[]> signedHashes,
+ Date creationTimestamp) {
+
+ if (!secretKey.isMasterKey()) {
+ throw new AssertionError("tried to certify with non-master key, this is a programming error!");
+ }
+ if (publicRing.getMasterKeyId() == secretKey.getKeyId()) {
+ throw new AssertionError("key tried to self-certify, this is a programming error!");
+ }
+
+ // create a signatureGenerator from the supplied masterKeyId and passphrase
+ PGPSignatureGenerator signatureGenerator = secretKey.getCertSignatureGenerator(signedHashes);
+
+ { // supply signatureGenerator with a SubpacketVector
+ PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
+ if (creationTimestamp != null) {
+ spGen.setSignatureCreationTime(false, creationTimestamp);
+ Log.d(Constants.TAG, "For NFC: set sig creation time to " + creationTimestamp);
+ }
+ PGPSignatureSubpacketVector packetVector = spGen.generate();
+ signatureGenerator.setHashedSubpackets(packetVector);
+ }
+
+ // get the master subkey (which we certify for)
+ PGPPublicKey publicKey = publicRing.getPublicKey().getPublicKey();
+
+ NfcSignOperationsBuilder requiredInput = new NfcSignOperationsBuilder(creationTimestamp);
+
+ try {
+ if (action.mUserIds != null) {
+ log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(),
+ KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
+
+ // fetch public key ring, add the certification and return it
+ for (String userId : action.mUserIds) {
+ try {
+ PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
+ publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
+ } catch (NfcInteractionNeeded e) {
+ requiredInput.addHash(e.hashToSign, e.hashAlgo);
+ }
+ }
+
+ }
+
+ if (action.mUserAttributes != null) {
+ log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, action.mUserAttributes.size(),
+ KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
+
+ // fetch public key ring, add the certification and return it
+ for (WrappedUserAttribute userAttribute : action.mUserAttributes) {
+ PGPUserAttributeSubpacketVector vector = userAttribute.getVector();
+ try {
+ PGPSignature sig = signatureGenerator.generateCertification(vector, publicKey);
+ publicKey = PGPPublicKey.addCertification(publicKey, vector, sig);
+ } catch (NfcInteractionNeeded e) {
+ requiredInput.addHash(e.hashToSign, e.hashAlgo);
+ }
+ }
+
+ }
+ } catch (PGPException e) {
+ Log.e(Constants.TAG, "signing error", e);
+ return new PgpCertifyResult();
+ }
+
+ if (!requiredInput.isEmpty()) {
+ return new PgpCertifyResult(requiredInput.build());
+ }
+
+ PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicRing.getRing(), publicKey);
+ return new PgpCertifyResult(new UncachedKeyRing(ring));
+
+ }
+
+ public static class PgpCertifyResult {
+
+ final RequiredInputParcel mRequiredInput;
+ final UncachedKeyRing mCertifiedRing;
+
+ PgpCertifyResult() {
+ mRequiredInput = null;
+ mCertifiedRing = null;
+ }
+
+ PgpCertifyResult(RequiredInputParcel requiredInput) {
+ mRequiredInput = requiredInput;
+ mCertifiedRing = null;
+ }
+
+ PgpCertifyResult(UncachedKeyRing certifiedRing) {
+ mRequiredInput = null;
+ mCertifiedRing = certifiedRing;
+ }
+
+ public boolean success() {
+ return mCertifiedRing != null || mRequiredInput != null;
+ }
+
+ public boolean nfcInputRequired() {
+ return mRequiredInput != null;
+ }
+
+ public UncachedKeyRing getCertifiedRing() {
+ return mCertifiedRing;
+ }
+
+ public RequiredInputParcel getRequiredInput() {
+ return mRequiredInput;
+ }
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
index b3bf92364..092fd9d48 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -18,7 +18,7 @@
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.KeyFlags;
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.PBESecretKeyEncryptor;
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
+import org.spongycastle.openpgp.operator.PGPDataDecryptor;
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
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.JcePBESecretKeyDecryptorBuilder;
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.R;
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.Curve;
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.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
@@ -86,9 +92,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
* This indicator may be null.
*/
public class PgpKeyOperation {
+
private Stack<Progressable> mProgress;
private AtomicBoolean mCancelled;
+ NfcSignOperationsBuilder mNfcSignOps;
+ private CryptoInputParcel mCryptoInput;
+
public PgpKeyOperation(Progressable progress) {
super();
if (progress != null) {
@@ -97,9 +107,11 @@ public class PgpKeyOperation {
}
}
- public PgpKeyOperation(Progressable progress, AtomicBoolean cancelled) {
+ public PgpKeyOperation(Progressable progress, AtomicBoolean cancelled, CryptoInputParcel cryptoInput) {
this(progress);
mCancelled = cancelled;
+ mNfcSignOps = new NfcSignOperationsBuilder(cryptoInput.getSignatureTime());
+ mCryptoInput = cryptoInput;
}
private boolean checkCancelled() {
@@ -317,7 +329,8 @@ public class PgpKeyOperation {
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
subProgressPush(50, 100);
- return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, new Passphrase(), log);
+ mCryptoInput = new CryptoInputParcel(new Date(), new Passphrase(""));
+ return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, log);
} catch (PGPException e) {
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
@@ -348,8 +361,8 @@ public class PgpKeyOperation {
* namely stripping of subkeys and changing the protection mode of dummy keys.
*
*/
- public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel,
- Passphrase passphrase) {
+ public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR,
+ SaveKeyringParcel saveParcel) {
OperationLog log = new OperationLog();
int indent = 0;
@@ -387,11 +400,16 @@ public class PgpKeyOperation {
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
- // If we have no passphrase, only allow restricted operation
- if (passphrase == null) {
+ if (saveParcel.isRestrictedOnly()) {
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.
// since this is the master key, this contains at least CERTIFY_OTHER
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
@@ -399,13 +417,13 @@ public class PgpKeyOperation {
Date expiryTime = wsKR.getPublicKey().getExpiryTime();
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,
int masterKeyFlags, long masterKeyExpiry,
- SaveKeyringParcel saveParcel, Passphrase passphrase,
+ SaveKeyringParcel saveParcel,
OperationLog log) {
int indent = 1;
@@ -414,18 +432,25 @@ public class PgpKeyOperation {
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
- // 1. Unlock private key
- progress(R.string.progress_modify_unlock, 10);
- log.add(LogType.MSG_MF_UNLOCK, indent);
PGPPrivateKey masterPrivateKey;
- {
- try {
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
- masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
- } catch (PGPException e) {
- log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
- return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+
+ if (isDivertToCard(masterSecretKey)) {
+ masterPrivateKey = null;
+ log.add(LogType.MSG_MF_DIVERT, indent);
+ } else {
+
+ // 1. Unlock private key
+ 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().getCharArray());
+ masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
+ } catch (PGPException e) {
+ log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
}
}
@@ -480,9 +505,16 @@ public class PgpKeyOperation {
boolean isPrimary = saveParcel.mChangePrimaryUserId != null
&& userId.equals(saveParcel.mChangePrimaryUserId);
// generate and add new certificate
- PGPSignature cert = generateUserIdSignature(masterPrivateKey,
- masterPublicKey, userId, isPrimary, masterKeyFlags, masterKeyExpiry);
- modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
+ try {
+ PGPSignature cert = generateUserIdSignature(
+ 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();
@@ -509,9 +541,15 @@ public class PgpKeyOperation {
PGPUserAttributeSubpacketVector vector = attribute.getVector();
// generate and add new certificate
- PGPSignature cert = generateUserAttributeSignature(masterPrivateKey,
- masterPublicKey, vector);
- modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, vector, cert);
+ try {
+ PGPSignature cert = generateUserAttributeSignature(
+ getSignatureGenerator(masterSecretKey, mCryptoInput),
+ mCryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, vector);
+ modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, vector, cert);
+ } catch (NfcInteractionNeeded e) {
+ mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
}
subProgressPop();
@@ -539,9 +577,15 @@ public class PgpKeyOperation {
// a duplicate revocation will be removed during canonicalization, so no need to
// take care of that here.
- PGPSignature cert = generateRevocationSignature(masterPrivateKey,
- masterPublicKey, userId);
- modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
+ try {
+ PGPSignature cert = generateRevocationSignature(
+ getSignatureGenerator(masterSecretKey, mCryptoInput),
+ mCryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, userId);
+ modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
+ } catch (NfcInteractionNeeded e) {
+ mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
}
subProgressPop();
@@ -611,11 +655,18 @@ public class PgpKeyOperation {
log.add(LogType.MSG_MF_PRIMARY_REPLACE_OLD, indent);
modifiedPublicKey = PGPPublicKey.removeCertification(
modifiedPublicKey, userId, currentCert);
- PGPSignature newCert = generateUserIdSignature(
- masterPrivateKey, masterPublicKey, userId, false,
- masterKeyFlags, masterKeyExpiry);
- modifiedPublicKey = PGPPublicKey.addCertification(
- modifiedPublicKey, userId, newCert);
+ try {
+ PGPSignature newCert = generateUserIdSignature(
+ getSignatureGenerator(masterSecretKey, mCryptoInput),
+ mCryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, userId, false,
+ masterKeyFlags, masterKeyExpiry);
+ modifiedPublicKey = PGPPublicKey.addCertification(
+ modifiedPublicKey, userId, newCert);
+ } catch (NfcInteractionNeeded e) {
+ mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
+
continue;
}
@@ -627,11 +678,17 @@ public class PgpKeyOperation {
log.add(LogType.MSG_MF_PRIMARY_NEW, indent);
modifiedPublicKey = PGPPublicKey.removeCertification(
modifiedPublicKey, userId, currentCert);
- PGPSignature newCert = generateUserIdSignature(
- masterPrivateKey, masterPublicKey, userId, true,
- masterKeyFlags, masterKeyExpiry);
- modifiedPublicKey = PGPPublicKey.addCertification(
- modifiedPublicKey, userId, newCert);
+ try {
+ PGPSignature newCert = generateUserIdSignature(
+ getSignatureGenerator(masterSecretKey, mCryptoInput),
+ mCryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, userId, true,
+ masterKeyFlags, masterKeyExpiry);
+ modifiedPublicKey = PGPPublicKey.addCertification(
+ modifiedPublicKey, userId, newCert);
+ } catch (NfcInteractionNeeded e) {
+ mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
ok = true;
}
@@ -718,7 +775,8 @@ public class PgpKeyOperation {
}
PGPPublicKey pKey =
- updateMasterCertificates(masterPrivateKey, masterPublicKey,
+ updateMasterCertificates(
+ masterSecretKey, masterPrivateKey, masterPublicKey,
flags, expiry, indent, log);
if (pKey == null) {
// error log entry has already been added by updateMasterCertificates itself
@@ -756,9 +814,16 @@ public class PgpKeyOperation {
pKey = PGPPublicKey.removeCertification(pKey, sig);
}
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ mCryptoInput.getPassphrase().getCharArray());
+ PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
+ PGPSignature sig = generateSubkeyBindingSignature(
+ getSignatureGenerator(masterSecretKey, mCryptoInput),
+ mCryptoInput.getSignatureTime(),
+ masterPublicKey, masterPrivateKey, subPrivateKey, pKey, flags, expiry);
+
// generate and add new signature
- PGPSignature sig = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey,
- sKey, pKey, flags, expiry, passphrase);
pKey = PGPPublicKey.addCertification(pKey, sig);
sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
}
@@ -782,10 +847,17 @@ public class PgpKeyOperation {
PGPPublicKey pKey = sKey.getPublicKey();
// generate and add new signature
- PGPSignature sig = generateRevocationSignature(masterPublicKey, masterPrivateKey, pKey);
-
- pKey = PGPPublicKey.addCertification(pKey, sig);
- sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
+ try {
+ PGPSignature sig = generateRevocationSignature(
+ getSignatureGenerator(masterSecretKey, mCryptoInput),
+ mCryptoInput.getSignatureTime(),
+ masterPublicKey, masterPrivateKey, pKey);
+
+ pKey = PGPPublicKey.addCertification(pKey, sig);
+ sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
+ } catch (NfcInteractionNeeded e) {
+ mNfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
}
subProgressPop();
@@ -828,10 +900,16 @@ public class PgpKeyOperation {
// add subkey binding signature (making this a sub rather than master key)
PGPPublicKey pKey = keyPair.getPublicKey();
- PGPSignature cert = generateSubkeyBindingSignature(
- masterPublicKey, masterPrivateKey, keyPair.getPrivateKey(), pKey,
- add.mFlags, add.mExpiry);
- pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
+ try {
+ PGPSignature cert = generateSubkeyBindingSignature(
+ getSignatureGenerator(masterSecretKey, mCryptoInput),
+ 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; {
// Build key encrypter and decrypter based on passphrase
@@ -840,7 +918,8 @@ public class PgpKeyOperation {
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ mCryptoInput.getPassphrase().getCharArray());
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
@@ -868,7 +947,7 @@ public class PgpKeyOperation {
indent += 1;
sKR = applyNewUnlock(sKR, masterPublicKey, masterPrivateKey,
- passphrase, saveParcel.mNewUnlock, log, indent);
+ mCryptoInput.getPassphrase(), saveParcel.mNewUnlock, log, indent);
if (sKR == null) {
// The error has been logged above, just return a bad state
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
@@ -892,6 +971,12 @@ public class PgpKeyOperation {
}
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);
return new PgpEditKeyResult(OperationResult.RESULT_OK, log, new UncachedKeyRing(sKR));
@@ -1064,8 +1149,7 @@ public class PgpKeyOperation {
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- newPassphrase.getCharArray());
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
// noinspection unchecked
for (PGPSecretKey sKey : new IterableIterator<PGPSecretKey>(sKR.getSecretKeys())) {
@@ -1116,8 +1200,9 @@ public class PgpKeyOperation {
}
/** Update all (non-revoked) uid signatures with new flags and expiry time. */
- private static PGPPublicKey updateMasterCertificates(
- PGPPrivateKey masterPrivateKey, PGPPublicKey masterPublicKey,
+ private PGPPublicKey updateMasterCertificates(
+ PGPSecretKey masterSecretKey, PGPPrivateKey masterPrivateKey,
+ PGPPublicKey masterPublicKey,
int flags, long expiry, int indent, OperationLog log)
throws PGPException, IOException, SignatureException {
@@ -1173,10 +1258,16 @@ public class PgpKeyOperation {
currentCert.getHashedSubPackets().isPrimaryUserID();
modifiedPublicKey = PGPPublicKey.removeCertification(
modifiedPublicKey, userId, currentCert);
- PGPSignature newCert = generateUserIdSignature(
- masterPrivateKey, masterPublicKey, userId, isPrimary, flags, expiry);
- modifiedPublicKey = PGPPublicKey.addCertification(
- modifiedPublicKey, userId, newCert);
+ try {
+ PGPSignature newCert = generateUserIdSignature(
+ getSignatureGenerator(masterSecretKey, mCryptoInput),
+ 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;
}
@@ -1191,15 +1282,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,
int flags, long expiry)
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();
{
@@ -1223,7 +1336,7 @@ public class PgpKeyOperation {
hashedPacketsGen.setPrimaryUserID(false, primary);
/* 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)
hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION);
hashedPacketsGen.setKeyFlags(true, flags);
@@ -1239,19 +1352,15 @@ public class PgpKeyOperation {
}
private static PGPSignature generateUserAttributeSignature(
+ PGPSignatureGenerator sGen, Date creationTime,
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey,
PGPUserAttributeSubpacketVector vector)
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();
{
/* critical subpackets: we consider those important for a modern pgp implementation */
- hashedPacketsGen.setSignatureCreationTime(true, new Date());
+ hashedPacketsGen.setSignatureCreationTime(true, creationTime);
}
sGen.setHashedSubpackets(hashedPacketsGen.generate());
@@ -1260,29 +1369,24 @@ public class PgpKeyOperation {
}
private static PGPSignature generateRevocationSignature(
+ PGPSignatureGenerator sGen, Date creationTime,
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId)
+
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();
- subHashedPacketsGen.setSignatureCreationTime(true, new Date());
+ subHashedPacketsGen.setSignatureCreationTime(true, creationTime);
sGen.setHashedSubpackets(subHashedPacketsGen.generate());
sGen.init(PGPSignature.CERTIFICATION_REVOCATION, masterPrivateKey);
return sGen.generateCertification(userId, pKey);
}
private static PGPSignature generateRevocationSignature(
+ PGPSignatureGenerator sGen, Date creationTime,
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey)
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();
- subHashedPacketsGen.setSignatureCreationTime(true, new Date());
+ subHashedPacketsGen.setSignatureCreationTime(true, creationTime);
sGen.setHashedSubpackets(subHashedPacketsGen.generate());
// Generate key revocation or subkey revocation, depending on master/subkey-ness
if (masterPublicKey.getKeyID() == pKey.getKeyID()) {
@@ -1294,26 +1398,12 @@ public class PgpKeyOperation {
}
}
- private static PGPSignature generateSubkeyBindingSignature(
- PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
- PGPSecretKey sKey, PGPPublicKey pKey, int flags, long expiry, Passphrase passphrase)
- throws IOException, PGPException, SignatureException {
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- passphrase.getCharArray());
- PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
- return generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, subPrivateKey,
- pKey, flags, expiry);
- }
-
static PGPSignature generateSubkeyBindingSignature(
+ PGPSignatureGenerator sGen, Date creationTime,
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
PGPPrivateKey subPrivateKey, PGPPublicKey pKey, int flags, long expiry)
throws IOException, PGPException, SignatureException {
- // date for signing
- Date creationTime = new Date();
-
PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
// If this key can sign, we need a primary key binding signature
@@ -1324,10 +1414,10 @@ public class PgpKeyOperation {
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
- sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey);
- sGen.setHashedSubpackets(subHashedPacketsGen.generate());
- PGPSignature certification = sGen.generateCertification(masterPublicKey, pKey);
+ PGPSignatureGenerator subSigGen = new PGPSignatureGenerator(signerBuilder);
+ subSigGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey);
+ subSigGen.setHashedSubpackets(subHashedPacketsGen.generate());
+ PGPSignature certification = subSigGen.generateCertification(masterPublicKey, pKey);
unhashedPacketsGen.setEmbeddedSignature(true, certification);
}
@@ -1342,10 +1432,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.setHashedSubpackets(hashedPacketsGen.generate());
sGen.setUnhashedSubpackets(unhashedPacketsGen.generate());
@@ -1372,4 +1458,10 @@ public class PgpKeyOperation {
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;
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
index 4a920685a..022dc4d32 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
@@ -20,11 +20,18 @@ package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.util.Passphrase;
+import java.nio.ByteBuffer;
import java.util.Date;
+import java.util.Map;
-public class PgpSignEncryptInput {
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+public class PgpSignEncryptInputParcel implements Parcelable {
protected String mVersionHeader = null;
protected boolean mEnableAsciiArmorOutput = false;
@@ -37,13 +44,73 @@ public class PgpSignEncryptInput {
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
protected Passphrase mSignaturePassphrase = null;
protected long mAdditionalEncryptId = Constants.key.none;
- protected byte[] mNfcSignedHash = null;
- protected Date mNfcCreationTimestamp = null;
protected boolean mFailOnMissingEncryptionKeyIds = false;
protected String mCharset;
protected boolean mCleartextSignature;
protected boolean mDetachedSignature = false;
protected boolean mHiddenRecipients = false;
+ protected CryptoInputParcel mCryptoInput = new CryptoInputParcel(null);
+
+ public PgpSignEncryptInputParcel() {
+
+ }
+
+ PgpSignEncryptInputParcel(Parcel source) {
+
+ ClassLoader loader = getClass().getClassLoader();
+
+ // we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
+ mVersionHeader = source.readString();
+ mEnableAsciiArmorOutput = source.readInt() == 1;
+ mCompressionId = source.readInt();
+ mEncryptionMasterKeyIds = source.createLongArray();
+ mSymmetricPassphrase = source.readParcelable(loader);
+ mSymmetricEncryptionAlgorithm = source.readInt();
+ mSignatureMasterKeyId = source.readLong();
+ mSignatureSubKeyId = source.readInt() == 1 ? source.readLong() : null;
+ mSignatureHashAlgorithm = source.readInt();
+ mSignaturePassphrase = source.readParcelable(loader);
+ mAdditionalEncryptId = source.readLong();
+ mFailOnMissingEncryptionKeyIds = source.readInt() == 1;
+ mCharset = source.readString();
+ mCleartextSignature = source.readInt() == 1;
+ mDetachedSignature = source.readInt() == 1;
+ mHiddenRecipients = source.readInt() == 1;
+
+ mCryptoInput = source.readParcelable(loader);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mVersionHeader);
+ dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
+ dest.writeInt(mCompressionId);
+ dest.writeLongArray(mEncryptionMasterKeyIds);
+ dest.writeParcelable(mSymmetricPassphrase, 0);
+ dest.writeInt(mSymmetricEncryptionAlgorithm);
+ dest.writeLong(mSignatureMasterKeyId);
+ if (mSignatureSubKeyId != null) {
+ dest.writeInt(1);
+ dest.writeLong(mSignatureSubKeyId);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeInt(mSignatureHashAlgorithm);
+ dest.writeParcelable(mSignaturePassphrase, 0);
+ dest.writeLong(mAdditionalEncryptId);
+ dest.writeInt(mFailOnMissingEncryptionKeyIds ? 1 : 0);
+ dest.writeString(mCharset);
+ dest.writeInt(mCleartextSignature ? 1 : 0);
+ dest.writeInt(mDetachedSignature ? 1 : 0);
+ dest.writeInt(mHiddenRecipients ? 1 : 0);
+
+ dest.writeParcelable(mCryptoInput, 0);
+ }
public String getCharset() {
return mCharset;
@@ -57,19 +124,11 @@ public class PgpSignEncryptInput {
return mFailOnMissingEncryptionKeyIds;
}
- public Date getNfcCreationTimestamp() {
- return mNfcCreationTimestamp;
- }
-
- public byte[] getNfcSignedHash() {
- return mNfcSignedHash;
- }
-
public long getAdditionalEncryptId() {
return mAdditionalEncryptId;
}
- public PgpSignEncryptInput setAdditionalEncryptId(long additionalEncryptId) {
+ public PgpSignEncryptInputParcel setAdditionalEncryptId(long additionalEncryptId) {
mAdditionalEncryptId = additionalEncryptId;
return this;
}
@@ -78,7 +137,7 @@ public class PgpSignEncryptInput {
return mSignaturePassphrase;
}
- public PgpSignEncryptInput setSignaturePassphrase(Passphrase signaturePassphrase) {
+ public PgpSignEncryptInputParcel setSignaturePassphrase(Passphrase signaturePassphrase) {
mSignaturePassphrase = signaturePassphrase;
return this;
}
@@ -87,7 +146,7 @@ public class PgpSignEncryptInput {
return mSignatureHashAlgorithm;
}
- public PgpSignEncryptInput setSignatureHashAlgorithm(int signatureHashAlgorithm) {
+ public PgpSignEncryptInputParcel setSignatureHashAlgorithm(int signatureHashAlgorithm) {
mSignatureHashAlgorithm = signatureHashAlgorithm;
return this;
}
@@ -96,7 +155,7 @@ public class PgpSignEncryptInput {
return mSignatureSubKeyId;
}
- public PgpSignEncryptInput setSignatureSubKeyId(long signatureSubKeyId) {
+ public PgpSignEncryptInputParcel setSignatureSubKeyId(long signatureSubKeyId) {
mSignatureSubKeyId = signatureSubKeyId;
return this;
}
@@ -105,7 +164,7 @@ public class PgpSignEncryptInput {
return mSignatureMasterKeyId;
}
- public PgpSignEncryptInput setSignatureMasterKeyId(long signatureMasterKeyId) {
+ public PgpSignEncryptInputParcel setSignatureMasterKeyId(long signatureMasterKeyId) {
mSignatureMasterKeyId = signatureMasterKeyId;
return this;
}
@@ -114,7 +173,7 @@ public class PgpSignEncryptInput {
return mSymmetricEncryptionAlgorithm;
}
- public PgpSignEncryptInput setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
+ public PgpSignEncryptInputParcel setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
return this;
}
@@ -123,7 +182,7 @@ public class PgpSignEncryptInput {
return mSymmetricPassphrase;
}
- public PgpSignEncryptInput setSymmetricPassphrase(Passphrase symmetricPassphrase) {
+ public PgpSignEncryptInputParcel setSymmetricPassphrase(Passphrase symmetricPassphrase) {
mSymmetricPassphrase = symmetricPassphrase;
return this;
}
@@ -132,7 +191,7 @@ public class PgpSignEncryptInput {
return mEncryptionMasterKeyIds;
}
- public PgpSignEncryptInput setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) {
+ public PgpSignEncryptInputParcel setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) {
mEncryptionMasterKeyIds = encryptionMasterKeyIds;
return this;
}
@@ -141,7 +200,7 @@ public class PgpSignEncryptInput {
return mCompressionId;
}
- public PgpSignEncryptInput setCompressionId(int compressionId) {
+ public PgpSignEncryptInputParcel setCompressionId(int compressionId) {
mCompressionId = compressionId;
return this;
}
@@ -154,28 +213,22 @@ public class PgpSignEncryptInput {
return mVersionHeader;
}
- public PgpSignEncryptInput setVersionHeader(String versionHeader) {
+ public PgpSignEncryptInputParcel setVersionHeader(String versionHeader) {
mVersionHeader = versionHeader;
return this;
}
- public PgpSignEncryptInput setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
+ public PgpSignEncryptInputParcel setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
mEnableAsciiArmorOutput = enableAsciiArmorOutput;
return this;
}
- public PgpSignEncryptInput setFailOnMissingEncryptionKeyIds(boolean failOnMissingEncryptionKeyIds) {
+ public PgpSignEncryptInputParcel setFailOnMissingEncryptionKeyIds(boolean failOnMissingEncryptionKeyIds) {
mFailOnMissingEncryptionKeyIds = failOnMissingEncryptionKeyIds;
return this;
}
- public PgpSignEncryptInput setNfcState(byte[] signedHash, Date creationTimestamp) {
- mNfcSignedHash = signedHash;
- mNfcCreationTimestamp = creationTimestamp;
- return this;
- }
-
- public PgpSignEncryptInput setCleartextSignature(boolean cleartextSignature) {
+ public PgpSignEncryptInputParcel setCleartextSignature(boolean cleartextSignature) {
this.mCleartextSignature = cleartextSignature;
return this;
}
@@ -184,7 +237,7 @@ public class PgpSignEncryptInput {
return mCleartextSignature;
}
- public PgpSignEncryptInput setDetachedSignature(boolean detachedSignature) {
+ public PgpSignEncryptInputParcel setDetachedSignature(boolean detachedSignature) {
this.mDetachedSignature = detachedSignature;
return this;
}
@@ -193,7 +246,7 @@ public class PgpSignEncryptInput {
return mDetachedSignature;
}
- public PgpSignEncryptInput setHiddenRecipients(boolean hiddenRecipients) {
+ public PgpSignEncryptInputParcel setHiddenRecipients(boolean hiddenRecipients) {
this.mHiddenRecipients = hiddenRecipients;
return this;
}
@@ -201,5 +254,29 @@ public class PgpSignEncryptInput {
public boolean isHiddenRecipients() {
return mHiddenRecipients;
}
+
+ public PgpSignEncryptInputParcel setCryptoInput(CryptoInputParcel cryptoInput) {
+ mCryptoInput = cryptoInput;
+ return this;
+ }
+
+ public Map<ByteBuffer, byte[]> getCryptoData() {
+ return mCryptoInput.getCryptoData();
+ }
+
+ public Date getSignatureTime() {
+ return mCryptoInput.getSignatureTime();
+ }
+
+ public static final Creator<PgpSignEncryptInputParcel> CREATOR = new Creator<PgpSignEncryptInputParcel>() {
+ public PgpSignEncryptInputParcel createFromParcel(final Parcel source) {
+ return new PgpSignEncryptInputParcel(source);
+ }
+
+ public PgpSignEncryptInputParcel[] newArray(final int size) {
+ return new PgpSignEncryptInputParcel[size];
+ }
+ };
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
index bd3c31d3a..7e70b4571 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
@@ -71,7 +71,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
*
* For a high-level operation based on URIs, see SignEncryptOperation.
*
- * @see org.sufficientlysecure.keychain.pgp.PgpSignEncryptInput
+ * @see PgpSignEncryptInputParcel
* @see org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult
* @see org.sufficientlysecure.keychain.operations.SignEncryptOperation
*
@@ -99,7 +99,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
/**
* Signs and/or encrypts data based on parameters of class
*/
- public PgpSignEncryptResult execute(PgpSignEncryptInput input,
+ public PgpSignEncryptResult execute(PgpSignEncryptInputParcel input,
InputData inputData, OutputStream outputStream) {
int indent = 0;
@@ -281,8 +281,9 @@ public class PgpSignEncryptOperation extends BaseOperation {
try {
boolean cleartext = input.isCleartextSignature() && input.isEnableAsciiArmorOutput() && !enableEncryption;
- signatureGenerator = signingKey.getSignatureGenerator(
- input.getSignatureHashAlgorithm(), cleartext, input.getNfcSignedHash(), input.getNfcCreationTimestamp());
+ signatureGenerator = signingKey.getDataSignatureGenerator(
+ input.getSignatureHashAlgorithm(), cleartext,
+ input.getCryptoData(), input.getSignatureTime());
} catch (PgpGeneralException e) {
log.add(LogType.MSG_PSE_ERROR_NFC, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
@@ -489,7 +490,8 @@ public class PgpSignEncryptOperation extends BaseOperation {
new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_PENDING_NFC, log);
// Note that the checked key here is the master key, not the signing key
// (although these are always the same on Yubikeys)
- result.setNfcData(input.getSignatureSubKeyId(), e.hashToSign, e.hashAlgo, e.creationTimestamp, input.getSignaturePassphrase());
+ result.setNfcData(signingKey.getKeyId(), e.hashToSign, e.hashAlgo,
+ input.getSignaturePassphrase());
Log.d(Constants.TAG, "e.hashToSign" + Hex.toHexString(e.hashToSign));
return result;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
index 975548c95..b178e9515 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
@@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.pgp;
import android.net.Uri;
import android.os.Parcel;
-import android.os.Parcelable;
import org.sufficientlysecure.keychain.util.Passphrase;
@@ -42,7 +41,7 @@ import java.util.List;
* left, which will be returned in a byte array as part of the result parcel.
*
*/
-public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable {
+public class SignEncryptParcel extends PgpSignEncryptInputParcel {
public ArrayList<Uri> mInputUris = new ArrayList<>();
public ArrayList<Uri> mOutputUris = new ArrayList<>();
@@ -53,26 +52,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
}
public SignEncryptParcel(Parcel src) {
-
- // we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
- mVersionHeader = src.readString();
- mEnableAsciiArmorOutput = src.readInt() == 1;
- mCompressionId = src.readInt();
- mEncryptionMasterKeyIds = src.createLongArray();
- mSymmetricPassphrase = src.readParcelable(Passphrase.class.getClassLoader());
- mSymmetricEncryptionAlgorithm = src.readInt();
- mSignatureMasterKeyId = src.readLong();
- mSignatureSubKeyId = src.readInt() == 1 ? src.readLong() : null;
- mSignatureHashAlgorithm = src.readInt();
- mSignaturePassphrase = src.readParcelable(Passphrase.class.getClassLoader());
- mAdditionalEncryptId = src.readLong();
- mNfcSignedHash = src.createByteArray();
- mNfcCreationTimestamp = src.readInt() == 1 ? new Date(src.readLong()) : null;
- mFailOnMissingEncryptionKeyIds = src.readInt() == 1;
- mCharset = src.readString();
- mCleartextSignature = src.readInt() == 1;
- mDetachedSignature = src.readInt() == 1;
- mHiddenRecipients = src.readInt() == 1;
+ super(src);
mInputUris = src.createTypedArrayList(Uri.CREATOR);
mOutputUris = src.createTypedArrayList(Uri.CREATOR);
@@ -110,34 +90,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
}
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mVersionHeader);
- dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
- dest.writeInt(mCompressionId);
- dest.writeLongArray(mEncryptionMasterKeyIds);
- dest.writeParcelable(mSymmetricPassphrase, flags);
- dest.writeInt(mSymmetricEncryptionAlgorithm);
- dest.writeLong(mSignatureMasterKeyId);
- if (mSignatureSubKeyId != null) {
- dest.writeInt(1);
- dest.writeLong(mSignatureSubKeyId);
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(mSignatureHashAlgorithm);
- dest.writeParcelable(mSignaturePassphrase, flags);
- dest.writeLong(mAdditionalEncryptId);
- dest.writeByteArray(mNfcSignedHash);
- if (mNfcCreationTimestamp != null) {
- dest.writeInt(1);
- dest.writeLong(mNfcCreationTimestamp.getTime());
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(mFailOnMissingEncryptionKeyIds ? 1 : 0);
- dest.writeString(mCharset);
- dest.writeInt(mCleartextSignature ? 1 : 0);
- dest.writeInt(mDetachedSignature ? 1 : 0);
- dest.writeInt(mHiddenRecipients ? 1 : 0);
+ super.writeToParcel(dest, flags);
dest.writeTypedList(mInputUris);
dest.writeTypedList(mOutputUris);