aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java79
1 files changed, 72 insertions, 7 deletions
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 7a1d99927..a855dcac8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
@@ -24,6 +24,7 @@ import android.net.Uri;
import android.os.Parcelable;
import android.support.annotation.NonNull;
+import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.BCPGOutputStream;
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
@@ -58,6 +59,10 @@ import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import java.nio.ByteBuffer;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
@@ -165,6 +170,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
return executeInternal(input, cryptoInput, inputData, outputStream);
}
+
/**
* Signs and/or encrypts data based on parameters of class
*/
@@ -238,7 +244,10 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
}
// Make sure we are allowed to sign here!
- if (!signingKey.canSign()) {
+ if ((!signingKey.canSign() && !data.isSshAuth()) ||
+ (!signingKey.canAuthenticate() && data.isSshAuth())) {
+ Log.w(Constants.TAG, "canSign " + signingKey.canSign() + " canAuthenticate "
+ + signingKey.canAuthenticate() + " isSshAuth "+ data.isSshAuth());
log.add(LogType.MSG_PSE_ERROR_KEY_SIGN, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
@@ -298,7 +307,11 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
// Use requested hash algo
int requestedAlgorithm = data.getSignatureHashAlgorithm();
if (requestedAlgorithm == PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) {
- data.setSignatureHashAlgorithm(PgpSecurityConstants.DEFAULT_HASH_ALGORITHM);
+ if (data.isSshAuth()) {
+ data.setSignatureHashAlgorithm(HashAlgorithmTags.SHA1);
+ } else {
+ data.setSignatureHashAlgorithm(PgpSecurityConstants.DEFAULT_HASH_ALGORITHM);
+ }
}
}
updateProgress(R.string.progress_preparing_streams, 2, 100);
@@ -386,6 +399,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
ByteArrayOutputStream detachedByteOut = null;
ArmoredOutputStream detachedArmorOut = null;
BCPGOutputStream detachedBcpgOut = null;
+ MessageDigest raw_digest = null;
long opTime, startTime = System.currentTimeMillis();
@@ -491,6 +505,28 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
} else if (enableSignature && data.isDetachedSignature()) {
/* detached signature */
+ // JMM - GROSS HACK
+ //
+ // The PGP stack doesn't do signatures of arbitary data: it wants
+ // to use its own structure for the message, so we have
+ // to be creative. We let the pgp stack do its stuff, but when
+ // it calls out to the NFC stack, we catch it and swap the
+ // message digest for own own.
+ //
+ // this means we have to check cyrptoInput for the correct
+ // hash ourselves on the 2nd trip through when the
+ // client resents the request.
+ //
+
+ if (data.isSshAuth()) {
+ try {
+ raw_digest = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ log.add(LogType.MSG_PSE_ERROR_IO, indent);
+ return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
+ }
+ }
+
updateProgress(R.string.progress_signing, 8, 100);
log.add(LogType.MSG_PSE_SIGNING_DETACHED, indent);
@@ -515,6 +551,9 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
while ((length = in.read(buffer)) > 0) {
// no output stream is written, no changed to original data!
+ if (raw_digest != null)
+ raw_digest.update(buffer, 0, length);
+
signatureGenerator.update(buffer, 0, length);
alreadyWritten += length;
@@ -582,11 +621,37 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
signatureGenerator.generate().encode(pOut);
}
} catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) {
- // this secret key diverts to a OpenPGP card, throw exception with hash that will be signed
- log.add(LogType.MSG_PSE_PENDING_NFC, indent);
- return new PgpSignEncryptResult(log, RequiredInputParcel.createSecurityTokenSignOperation(
- signingKey.getRing().getMasterKeyId(), signingKey.getKeyId(),
- e.hashToSign, e.hashAlgo, cryptoInput.getSignatureTime()), cryptoInput);
+
+ // JMM - 2nd part of gross hack
+ // first swap the message digest for the raw one
+ // before this hits the NFC stack
+
+ if (raw_digest != null)
+ e.hashToSign = raw_digest.digest();
+
+ // Test to see if we already have the answer for the hash
+ // as the test in encode() above was checking the wrong
+ // hash.
+
+ byte [] answer = cryptoInput.getCryptoData().get(ByteBuffer.wrap(e.hashToSign));
+
+ if (raw_digest == null || answer == null) {
+ // We haven't done the hash yet, so kick it off to the NFC stack
+
+ // this secret key diverts to a OpenPGP card, throw exception with hash that will be signed
+
+ log.add(LogType.MSG_PSE_PENDING_NFC, indent);
+ return new PgpSignEncryptResult(log, RequiredInputParcel.createSecurityTokenSignOperation(
+ signingKey.getRing().getMasterKeyId(), signingKey.getKeyId(),
+ e.hashToSign, e.hashAlgo, cryptoInput.getSignatureTime()), cryptoInput);
+ } else if (raw_digest != null) {
+ // We've aready done the work, replace the output stream
+ // from the PGP signature with just the signature as we want just
+ // a raw signature
+
+ detachedByteOut = new ByteArrayOutputStream();
+ detachedByteOut.write(answer, 0, answer.length);
+ }
}
}