diff options
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.java | 79 |
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); + } } } |