diff options
| author | Vincent Breitmoser <valodim@mugenguild.com> | 2014-09-14 00:33:19 +0200 | 
|---|---|---|
| committer | Vincent Breitmoser <valodim@mugenguild.com> | 2014-09-14 00:33:30 +0200 | 
| commit | f0e159a372174db4d0939f8f747a05b62d9b068d (patch) | |
| tree | 00eb8eb73e04c39d37cac8d15bfc6f4ef08f4206 /OpenKeychain/src/main | |
| parent | 6156600e42407a6a810f3f8b294197de47095f74 (diff) | |
| download | open-keychain-f0e159a372174db4d0939f8f747a05b62d9b068d.tar.gz open-keychain-f0e159a372174db4d0939f8f747a05b62d9b068d.tar.bz2 open-keychain-f0e159a372174db4d0939f8f747a05b62d9b068d.zip  | |
add SignEncryptResult parcel (probably break stuff)
Diffstat (limited to 'OpenKeychain/src/main')
7 files changed, 301 insertions, 214 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 070239a80..9f97ac4c9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -35,6 +35,10 @@ import org.sufficientlysecure.keychain.R;  import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;  import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;  import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogLevel; +import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogType; +import org.sufficientlysecure.keychain.service.results.OperationResultParcel.OperationLog; +import org.sufficientlysecure.keychain.service.results.SignEncryptResult;  import org.sufficientlysecure.keychain.util.InputData;  import org.sufficientlysecure.keychain.util.Log;  import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -45,8 +49,6 @@ import java.io.InputStream;  import java.io.InputStreamReader;  import java.io.OutputStream;  import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException;  import java.security.SignatureException;  import java.util.Arrays;  import java.util.Date; @@ -247,44 +249,16 @@ public class PgpSignEncrypt {          }      } -    public static class KeyExtractionException extends Exception { -        public KeyExtractionException() { -        } -    } - -    public static class NoPassphraseException extends Exception { -        public NoPassphraseException() { -        } -    } - -    public static class WrongPassphraseException extends Exception { -        public WrongPassphraseException() { -        } -    } - -    public static class NoSigningKeyException extends Exception { -        public NoSigningKeyException() { -        } -    } - -    public static class NeedNfcDataException extends Exception { -        public byte[] mHashToSign; -        public int mHashAlgo; -        public Date mCreationTimestamp; - -        public NeedNfcDataException(byte[] hashToSign, int hashAlgo, Date creationTimestamp) { -            mHashToSign = hashToSign; -            mHashAlgo = hashAlgo; -            mCreationTimestamp = creationTimestamp; -        } -    } -      /**       * Signs and/or encrypts data based on parameters of class       */ -    public void execute() -            throws IOException, PGPException, NoSuchProviderException, -            NoSuchAlgorithmException, SignatureException, KeyExtractionException, NoSigningKeyException, NoPassphraseException, NeedNfcDataException, WrongPassphraseException { +    public SignEncryptResult execute() { + +        int indent = 0; +        OperationLog log = new OperationLog(); + +        log.add(LogLevel.START, LogType.MSG_SE, indent); +        indent += 1;          boolean enableSignature = mSignatureMasterKeyId != Constants.key.none;          boolean enableEncryption = ((mEncryptionMasterKeyIds != null && mEncryptionMasterKeyIds.length > 0) @@ -320,7 +294,8 @@ public class PgpSignEncrypt {              // If we weren't handed a passphrase, throw early              if (mSignaturePassphrase == null) { -                throw new NoPassphraseException(); +                log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_NO_PASSPHRASE, indent); +                return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);              }              try { @@ -332,22 +307,26 @@ public class PgpSignEncrypt {                  signingKey = signingKeyRing.getSecretKey(signKeyId);                  // make sure it's a signing key alright!              } catch (ProviderHelper.NotFoundException e) { -                throw new NoSigningKeyException(); +                log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_SIGN_KEY, indent); +                return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);              }              // Make sure we are allowed to sign here! -            if ( ! signingKey.canSign()) { -                throw new NoSigningKeyException(); +            if (!signingKey.canSign()) { +                log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_KEY_SIGN, indent); +                return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);              }              updateProgress(R.string.progress_extracting_signature_key, 0, 100);              try { -                if ( ! signingKey.unlock(mSignaturePassphrase)) { -                    throw new WrongPassphraseException(); +                if (!signingKey.unlock(mSignaturePassphrase)) { +                    log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_BAD_PASSPHRASE, indent); +                    return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);                  }              } catch (PgpGeneralException e) { -                throw new KeyExtractionException(); +                log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_UNLOCK, indent); +                return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);              }              // check if hash algo is supported @@ -372,12 +351,14 @@ public class PgpSignEncrypt {              if (mSymmetricPassphrase != null) {                  // Symmetric encryption -                Log.d(Constants.TAG, "encryptionMasterKeyIds length is 0 -> symmetric encryption"); +                log.add(LogLevel.DEBUG, LogType.MSG_SE_SYMMETRIC, indent);                  JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator =                          new JcePBEKeyEncryptionMethodGenerator(mSymmetricPassphrase.toCharArray());                  cPk.addMethod(symmetricEncryptionGenerator);              } else { +                log.add(LogLevel.INFO, LogType.MSG_SE_ASYMMETRIC, indent); +                  // Asymmetric encryption                  for (long id : mEncryptionMasterKeyIds) {                      try { @@ -385,10 +366,14 @@ public class PgpSignEncrypt {                                  KeyRings.buildUnifiedKeyRingUri(id));                          CanonicalizedPublicKey key = keyRing.getEncryptionSubKey();                          cPk.addMethod(key.getPubKeyEncryptionGenerator()); +                        log.add(LogLevel.DEBUG, LogType.MSG_SE_KEY_OK, indent +1, +                                PgpKeyHelper.convertKeyIdToHex(id));                      } catch (PgpGeneralException e) { -                        Log.e(Constants.TAG, "key not found!", e); +                        log.add(LogLevel.WARN, LogType.MSG_SE_KEY_WARN, indent +1, +                                PgpKeyHelper.convertKeyIdToHex(id));                      } catch (ProviderHelper.NotFoundException e) { -                        Log.e(Constants.TAG, "key not found!", e); +                        log.add(LogLevel.WARN, LogType.MSG_SE_KEY_UNKNOWN, indent +1, +                                PgpKeyHelper.convertKeyIdToHex(id));                      }                  }              } @@ -404,168 +389,199 @@ public class PgpSignEncrypt {                  signatureGenerator = signingKey.getSignatureGenerator(                          mSignatureHashAlgorithm, cleartext, mNfcSignedHash, mNfcCreationTimestamp);              } catch (PgpGeneralException e) { -                // TODO throw correct type of exception (which shouldn't be PGPException) -                throw new KeyExtractionException(); +                log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_NFC, indent); +                return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);              }          }          ProgressScaler progressScaler =                  new ProgressScaler(mProgressable, 8, 95, 100);          PGPCompressedDataGenerator compressGen = null; -        OutputStream pOut = null; +        OutputStream pOut;          OutputStream encryptionOut = null;          BCPGOutputStream bcpgOut; -        if (enableEncryption) { -            /* actual encryption */ -            updateProgress(R.string.progress_encrypting, 8, 100); - -            encryptionOut = cPk.open(out, new byte[1 << 16]); - -            if (enableCompression) { -                compressGen = new PGPCompressedDataGenerator(mCompressionId); -                bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut)); -            } else { -                bcpgOut = new BCPGOutputStream(encryptionOut); -            } - -            if (enableSignature) { -                signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); -            } - -            PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); -            char literalDataFormatTag; -            if (mCleartextInput) { -                literalDataFormatTag = PGPLiteralData.UTF8; -            } else { -                literalDataFormatTag = PGPLiteralData.BINARY; -            } -            pOut = literalGen.open(bcpgOut, literalDataFormatTag, mOriginalFilename, new Date(), -                    new byte[1 << 16]); +        try { -            long alreadyWritten = 0; -            int length; -            byte[] buffer = new byte[1 << 16]; -            InputStream in = mData.getInputStream(); -            while ((length = in.read(buffer)) > 0) { -                pOut.write(buffer, 0, length); +            if (enableEncryption) { +                /* actual encryption */ +                updateProgress(R.string.progress_encrypting, 8, 100); +                log.add(LogLevel.DEBUG, enableSignature +                        ? LogType.MSG_SE_SIGCRYPTING +                        : LogType.MSG_SE_ENCRYPTING, +                        indent); +                indent += 1; + +                encryptionOut = cPk.open(out, new byte[1 << 16]); + +                if (enableCompression) { +                    log.add(LogLevel.DEBUG, LogType.MSG_SE_COMPRESSING, indent); +                    compressGen = new PGPCompressedDataGenerator(mCompressionId); +                    bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut)); +                } else { +                    bcpgOut = new BCPGOutputStream(encryptionOut); +                } -                // update signature buffer if signature is requested                  if (enableSignature) { -                    signatureGenerator.update(buffer, 0, length); +                    signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);                  } -                alreadyWritten += length; -                if (mData.getSize() > 0) { -                    long progress = 100 * alreadyWritten / mData.getSize(); -                    progressScaler.setProgress((int) progress, 100); +                PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); +                char literalDataFormatTag; +                if (mCleartextInput) { +                    literalDataFormatTag = PGPLiteralData.UTF8; +                } else { +                    literalDataFormatTag = PGPLiteralData.BINARY; +                } +                pOut = literalGen.open(bcpgOut, literalDataFormatTag, mOriginalFilename, new Date(), +                        new byte[1 << 16]); + +                long alreadyWritten = 0; +                int length; +                byte[] buffer = new byte[1 << 16]; +                InputStream in = mData.getInputStream(); +                while ((length = in.read(buffer)) > 0) { +                    pOut.write(buffer, 0, length); + +                    // update signature buffer if signature is requested +                    if (enableSignature) { +                        signatureGenerator.update(buffer, 0, length); +                    } + +                    alreadyWritten += length; +                    if (mData.getSize() > 0) { +                        long progress = 100 * alreadyWritten / mData.getSize(); +                        progressScaler.setProgress((int) progress, 100); +                    }                  } -            } -            literalGen.close(); -        } else if (enableSignature && mCleartextInput && mEnableAsciiArmorOutput) { -            /* cleartext signature: sign-only of ascii text */ +                literalGen.close(); +                indent -= 1; -            updateProgress(R.string.progress_signing, 8, 100); +            } else if (enableSignature && mCleartextInput && mEnableAsciiArmorOutput) { +                /* cleartext signature: sign-only of ascii text */ -            // write -----BEGIN PGP SIGNED MESSAGE----- -            armorOut.beginClearText(mSignatureHashAlgorithm); +                updateProgress(R.string.progress_signing, 8, 100); +                log.add(LogLevel.DEBUG, LogType.MSG_SE_SIGNING, indent); -            InputStream in = mData.getInputStream(); -            final BufferedReader reader = new BufferedReader(new InputStreamReader(in)); +                // write -----BEGIN PGP SIGNED MESSAGE----- +                armorOut.beginClearText(mSignatureHashAlgorithm); -            // update signature buffer with first line -            processLine(reader.readLine(), armorOut, signatureGenerator); +                InputStream in = mData.getInputStream(); +                final BufferedReader reader = new BufferedReader(new InputStreamReader(in)); -            // TODO: progress: fake annealing? -            while (true) { -                String line = reader.readLine(); +                // update signature buffer with first line +                processLine(reader.readLine(), armorOut, signatureGenerator); + +                // TODO: progress: fake annealing? +                while (true) { +                    String line = reader.readLine(); + +                    // end cleartext signature with newline, see http://tools.ietf.org/html/rfc4880#section-7 +                    if (line == null) { +                        armorOut.write(NEW_LINE); +                        break; +                    } -                // end cleartext signature with newline, see http://tools.ietf.org/html/rfc4880#section-7 -                if (line == null) {                      armorOut.write(NEW_LINE); -                    break; + +                    // update signature buffer with input line +                    signatureGenerator.update(NEW_LINE); +                    processLine(line, armorOut, signatureGenerator);                  } -                armorOut.write(NEW_LINE); +                armorOut.endClearText(); -                // update signature buffer with input line -                signatureGenerator.update(NEW_LINE); -                processLine(line, armorOut, signatureGenerator); -            } +                pOut = new BCPGOutputStream(armorOut); +            } else if (enableSignature && !mCleartextInput) { +                /* sign-only binary (files/data stream) */ -            armorOut.endClearText(); +                updateProgress(R.string.progress_signing, 8, 100); +                log.add(LogLevel.DEBUG, LogType.MSG_SE_ENCRYPTING, indent); -            pOut = new BCPGOutputStream(armorOut); -        } else if (enableSignature && !mCleartextInput) { -            /* sign-only binary (files/data stream) */ +                InputStream in = mData.getInputStream(); -            updateProgress(R.string.progress_signing, 8, 100); +                if (enableCompression) { +                    compressGen = new PGPCompressedDataGenerator(mCompressionId); +                    bcpgOut = new BCPGOutputStream(compressGen.open(out)); +                } else { +                    bcpgOut = new BCPGOutputStream(out); +                } -            InputStream in = mData.getInputStream(); +                signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); -            if (enableCompression) { -                compressGen = new PGPCompressedDataGenerator(mCompressionId); -                bcpgOut = new BCPGOutputStream(compressGen.open(out)); -            } else { -                bcpgOut = new BCPGOutputStream(out); -            } +                PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); +                pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, mOriginalFilename, new Date(), +                        new byte[1 << 16]); -            signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); +                long alreadyWritten = 0; +                int length; +                byte[] buffer = new byte[1 << 16]; +                while ((length = in.read(buffer)) > 0) { +                    pOut.write(buffer, 0, length); -            PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); -            pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, mOriginalFilename, new Date(), -                    new byte[1 << 16]); +                    signatureGenerator.update(buffer, 0, length); -            long alreadyWritten = 0; -            int length; -            byte[] buffer = new byte[1 << 16]; -            while ((length = in.read(buffer)) > 0) { -                pOut.write(buffer, 0, length); +                    alreadyWritten += length; +                    if (mData.getSize() > 0) { +                        long progress = 100 * alreadyWritten / mData.getSize(); +                        progressScaler.setProgress((int) progress, 100); +                    } +                } -                signatureGenerator.update(buffer, 0, length); +                literalGen.close(); +            } else { +                pOut = null; +                log.add(LogLevel.WARN, LogType.MSG_SE_CLEARSIGN_ONLY, indent); +            } -                alreadyWritten += length; -                if (mData.getSize() > 0) { -                    long progress = 100 * alreadyWritten / mData.getSize(); -                    progressScaler.setProgress((int) progress, 100); +            if (enableSignature) { +                updateProgress(R.string.progress_generating_signature, 95, 100); +                try { +                    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(LogLevel.OK, LogType.MSG_SE_PENDING_NFC, indent); +                    SignEncryptResult result = +                            new SignEncryptResult(SignEncryptResult.RESULT_PENDING_NFC, log); +                    result.setNfcData(e.hashToSign, e.hashAlgo, e.creationTimestamp); +                    return new SignEncryptResult(SignEncryptResult.RESULT_PENDING_NFC, log);                  }              } -            literalGen.close(); -        } else { -            pOut = null; -            Log.e(Constants.TAG, "not supported!"); -        } +            // closing outputs +            // NOTE: closing needs to be done in the correct order! +            // TODO: closing bcpgOut and pOut??? +            if (enableEncryption) { +                if (enableCompression) { +                    compressGen.close(); +                } -        if (enableSignature) { -            updateProgress(R.string.progress_generating_signature, 95, 100); -            try { -                signatureGenerator.generate().encode(pOut); -            } catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) { -                // this secret key diverts to a OpenPGP card, throw exception with hash that will be signed -                throw new NeedNfcDataException(e.hashToSign, e.hashAlgo, e.creationTimestamp); +                encryptionOut.close();              } -        } - -        // closing outputs -        // NOTE: closing needs to be done in the correct order! -        // TODO: closing bcpgOut and pOut??? -        if (enableEncryption) { -            if (enableCompression) { -                compressGen.close(); +            if (mEnableAsciiArmorOutput) { +                armorOut.close();              } -            encryptionOut.close(); -        } -        if (mEnableAsciiArmorOutput) { -            armorOut.close(); -        } +            out.close(); +            mOutStream.close(); -        out.close(); -        mOutStream.close(); +        } catch (SignatureException e) { +            log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_SIG, indent); +            return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); +        } catch (PGPException e) { +            log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_PGP, indent); +            return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); +        } catch (IOException e) { +            log.add(LogLevel.ERROR, LogType.MSG_SE_ERROR_IO, indent); +            return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log); +        }          updateProgress(R.string.progress_done, 100, 100); + +        log.add(LogLevel.OK, LogType.MSG_SE_OK, indent); +        return new SignEncryptResult(SignEncryptResult.RESULT_OK, log); +      }      private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 205395dbf..29f888a82 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -45,6 +45,8 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;  import org.sufficientlysecure.keychain.provider.ProviderHelper;  import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity;  import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogEntryParcel; +import org.sufficientlysecure.keychain.service.results.SignEncryptResult;  import org.sufficientlysecure.keychain.ui.ImportKeysActivity;  import org.sufficientlysecure.keychain.ui.ViewKeyActivity;  import org.sufficientlysecure.keychain.util.InputData; @@ -269,25 +271,28 @@ public class OpenPgpService extends RemoteService {                  // TODO: currently always assume cleartext input, no sign-only of binary currently!                  builder.setCleartextInput(true); -                try { -                    builder.build().execute(); - -                    // throw exceptions upwards to client with meaningful messages -                } catch (PgpSignEncrypt.KeyExtractionException e) { -                    throw new Exception(getString(R.string.error_could_not_extract_private_key)); -                } catch (PgpSignEncrypt.NoPassphraseException e) { -                    throw new Exception(getString(R.string.error_no_signature_passphrase)); -                } catch (PgpSignEncrypt.WrongPassphraseException e) { -                    throw new Exception(getString(R.string.error_wrong_passphrase)); -                } catch (PgpSignEncrypt.NoSigningKeyException e) { -                    throw new Exception(getString(R.string.error_no_signature_key)); -                } catch (PgpSignEncrypt.NeedNfcDataException e) { -                    // return PendingIntent to execute NFC activity -                    // pass through the signature creation timestamp to be used again on second execution -                    // of PgpSignEncrypt when we have the signed hash! -                    data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, e.mCreationTimestamp.getTime()); -                    return getNfcSignIntent(data, passphrase, e.mHashToSign, e.mHashAlgo); +                // execute PGP operation! +                SignEncryptResult result = builder.build().execute(); + +                if (result.isPending()) { +                    switch (result.getResult()) { +                        case SignEncryptResult.RESULT_PENDING_NFC: +                            // return PendingIntent to execute NFC activity +                            // pass through the signature creation timestamp to be used again on second execution +                            // of PgpSignEncrypt when we have the signed hash! +                            data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, result.getNfcTimestamp().getTime()); +                            return getNfcSignIntent(data, passphrase, result.getNfcHash(), result.getNfcAlgo()); + +                        default: +                            throw new Exception("Encountered unhandled pending state - please file a bug report!"); +                    }                  } + +                if (!result.success()) { +                    LogEntryParcel errorMsg = result.getLog().getLast(); +                    throw new Exception(getString(errorMsg.mType.getMsgId())); +                } +              } finally {                  is.close();                  os.close(); @@ -379,26 +384,28 @@ public class OpenPgpService extends RemoteService {                              .setNfcState(nfcSignedHash, nfcCreationDate);                  } -                try { -                    // execute PGP operation! -                    builder.build().execute(); - -                    // throw exceptions upwards to client with meaningful messages -                } catch (PgpSignEncrypt.KeyExtractionException e) { -                    throw new Exception(getString(R.string.error_could_not_extract_private_key)); -                } catch (PgpSignEncrypt.NoPassphraseException e) { -                    throw new Exception(getString(R.string.error_no_signature_passphrase)); -                } catch (PgpSignEncrypt.WrongPassphraseException e) { -                    throw new Exception(getString(R.string.error_wrong_passphrase)); -                } catch (PgpSignEncrypt.NoSigningKeyException e) { -                    throw new Exception(getString(R.string.error_no_signature_key)); -                } catch (PgpSignEncrypt.NeedNfcDataException e) { -                    // return PendingIntent to execute NFC activity -                    // pass through the signature creation timestamp to be used again on second execution -                    // of PgpSignEncrypt when we have the signed hash! -                    data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, e.mCreationTimestamp.getTime()); -                    return getNfcSignIntent(data, passphrase, e.mHashToSign, e.mHashAlgo); +                // execute PGP operation! +                SignEncryptResult result = builder.build().execute(); + +                if (result.isPending()) { +                    switch (result.getResult()) { +                        case SignEncryptResult.RESULT_PENDING_NFC: +                            // return PendingIntent to execute NFC activity +                            // pass through the signature creation timestamp to be used again on second execution +                            // of PgpSignEncrypt when we have the signed hash! +                            data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, result.getNfcTimestamp().getTime()); +                            return getNfcSignIntent(data, passphrase, result.getNfcHash(), result.getNfcAlgo()); + +                        default: +                            throw new Exception("Encountered unhandled pending state - please file a bug report!"); +                    }                  } + +                if (!result.success()) { +                    LogEntryParcel errorMsg = result.getLog().getLast(); +                    throw new Exception(getString(errorMsg.mType.getMsgId())); +                } +              } finally {                  is.close();                  os.close(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index f8ef9b0f6..e09c71787 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -63,6 +63,7 @@ import org.sufficientlysecure.keychain.service.results.ConsolidateResult;  import org.sufficientlysecure.keychain.service.results.EditKeyResult;  import org.sufficientlysecure.keychain.service.results.ImportKeyResult;  import org.sufficientlysecure.keychain.service.results.SaveKeyringResult; +import org.sufficientlysecure.keychain.service.results.SignEncryptResult;  import org.sufficientlysecure.keychain.util.ParcelableFileCache;  import org.sufficientlysecure.keychain.util.InputData;  import org.sufficientlysecure.keychain.util.Log; @@ -91,7 +92,7 @@ public class KeychainIntentService extends IntentService implements Progressable      public static final String EXTRA_DATA = "data";      /* possible actions */ -    public static final String ACTION_ENCRYPT_SIGN = Constants.INTENT_PREFIX + "ENCRYPT_SIGN"; +    public static final String ACTION_SIGN_ENCRYPT = Constants.INTENT_PREFIX + "SIGN_ENCRYPT";      public static final String ACTION_DECRYPT_VERIFY = Constants.INTENT_PREFIX + "DECRYPT_VERIFY"; @@ -247,7 +248,7 @@ public class KeychainIntentService extends IntentService implements Progressable          String action = intent.getAction();          // executeServiceMethod action from extra bundle -        if (ACTION_ENCRYPT_SIGN.equals(action)) { +        if (ACTION_SIGN_ENCRYPT.equals(action)) {              try {                  /* Input */                  int source = data.get(SOURCE) != null ? data.getInt(SOURCE) : data.getInt(TARGET); @@ -309,7 +310,8 @@ public class KeychainIntentService extends IntentService implements Progressable                          builder.setCleartextInput(true);                      } -                    builder.build().execute(); +                    SignEncryptResult result = builder.build().execute(); +                    resultData.putParcelable(SignEncryptResult.EXTRA_RESULT, result);                      outStream.close(); @@ -779,12 +781,6 @@ public class KeychainIntentService extends IntentService implements Progressable          if (e instanceof PgpGeneralMsgIdException) {              e = ((PgpGeneralMsgIdException) e).getContextualized(this);              message = e.getMessage(); -        } else if (e instanceof PgpSignEncrypt.KeyExtractionException) { -            message = getString(R.string.error_could_not_extract_private_key); -        } else if (e instanceof PgpSignEncrypt.NoPassphraseException) { -            message = getString(R.string.error_no_signature_passphrase); -        } else if (e instanceof PgpSignEncrypt.NoSigningKeyException) { -            message = getString(R.string.error_no_signature_key);          } else {              message = e.getMessage();          } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResultParcel.java index 46823a24d..56f5248cb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResultParcel.java @@ -474,6 +474,30 @@ public class OperationResultParcel implements Parcelable {          MSG_DC_TRAIL_UNKNOWN (R.string.msg_dc_trail_unknown),          MSG_DC_UNLOCKING (R.string.msg_dc_unlocking), +        // signencrypt +        MSG_SE_ASYMMETRIC (R.string.msg_se_asymmetric), +        MSG_SE_CLEARSIGN_ONLY (R.string.msg_se_clearsign_only), +        MSG_SE_COMPRESSING (R.string.msg_se_compressing), +        MSG_SE_ENCRYPTING (R.string.msg_se_encrypting), +        MSG_SE_ERROR_BAD_PASSPHRASE (R.string.msg_se_error_bad_passphrase), +        MSG_SE_ERROR_IO (R.string.msg_se_error_io), +        MSG_SE_ERROR_SIGN_KEY(R.string.msg_se_error_sign_key), +        MSG_SE_ERROR_KEY_SIGN (R.string.msg_se_error_key_sign), +        MSG_SE_ERROR_NFC (R.string.msg_se_error_nfc), +        MSG_SE_ERROR_NO_PASSPHRASE (R.string.msg_se_error_no_passphrase), +        MSG_SE_ERROR_PGP (R.string.msg_se_error_pgp), +        MSG_SE_ERROR_SIG (R.string.msg_se_error_sig), +        MSG_SE_ERROR_UNLOCK (R.string.msg_se_error_unlock), +        MSG_SE_KEY_OK (R.string.msg_se_key_ok), +        MSG_SE_KEY_UNKNOWN (R.string.msg_se_key_unknown), +        MSG_SE_KEY_WARN (R.string.msg_se_key_warn), +        MSG_SE_OK (R.string.msg_se_ok), +        MSG_SE_PENDING_NFC (R.string.msg_se_pending_nfc), +        MSG_SE (R.string.msg_se), +        MSG_SE_SIGNING (R.string.msg_se_signing), +        MSG_SE_SIGCRYPTING (R.string.msg_se_sigcrypting), +        MSG_SE_SYMMETRIC (R.string.msg_se_symmetric), +          ;          private final int mMsgId; @@ -562,6 +586,13 @@ public class OperationResultParcel implements Parcelable {              return mParcels.isEmpty();          } +        public LogEntryParcel getLast() { +            if (mParcels.isEmpty()) { +                return null; +            } +            return mParcels.get(mParcels.size() -1); +        } +          @Override          public Iterator<LogEntryParcel> iterator() {              return mParcels.iterator(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileActivity.java index 96f8bd983..a5de20986 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileActivity.java @@ -183,7 +183,7 @@ public class EncryptFileActivity extends DrawerActivity implements EncryptActivi          // Send all information needed to service to edit key in other thread          Intent intent = new Intent(this, KeychainIntentService.class); -        intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); +        intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT);          intent.putExtra(KeychainIntentService.EXTRA_DATA, createEncryptBundle());          // Message is received after encrypting is done in KeychainIntentService diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 6e6e52562..4bf1cad3c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -42,6 +42,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;  import org.sufficientlysecure.keychain.service.KeychainIntentService;  import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;  import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.service.results.SignEncryptResult;  import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;  import org.sufficientlysecure.keychain.util.Log;  import org.sufficientlysecure.keychain.util.Notify; @@ -184,7 +185,7 @@ public class EncryptTextActivity extends DrawerActivity implements EncryptActivi          // Send all information needed to service to edit key in other thread          Intent intent = new Intent(this, KeychainIntentService.class); -        intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); +        intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT);          intent.putExtra(KeychainIntentService.EXTRA_DATA, createEncryptBundle());          // Message is received after encrypting is done in KeychainIntentService @@ -195,14 +196,26 @@ public class EncryptTextActivity extends DrawerActivity implements EncryptActivi                  super.handleMessage(message);                  if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + +                    SignEncryptResult result = +                            message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT); + +                    // TODO if (result.isPending()) + +                    if (!result.success()) { +                        result.createNotify(EncryptTextActivity.this).show(); +                        return; +                    } +                      if (mShareAfterEncrypt) {                          // Share encrypted message/file                          startActivity(sendWithChooserExcludingEncrypt(message));                      } else {                          // Copy to clipboard                          copyToClipboard(message); -                        Notify.showNotify(EncryptTextActivity.this, -                                R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO); +                        result.createNotify(EncryptTextActivity.this).show(); +                        // Notify.showNotify(EncryptTextActivity.this, +                                // R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO);                      }                  }              } diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 62299ed34..e1fcf4a0b 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -701,7 +701,7 @@      <string name="msg_mf_error_revoked_primary">"Revoked user ids cannot be primary!"</string>      <string name="msg_mf_error_null_expiry">"Expiry time cannot be "same as before" on subkey creation. This is 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">"PGP internal exception!"</string> +    <string name="msg_mf_error_pgp">"Internal PGP error!"</string>      <string name="msg_mf_error_sig">"Signature exception!"</string>      <string name="msg_mf_master">"Modifying master certifications"</string>      <string name="msg_mf_passphrase">"Changing passphrase for keyring…"</string> @@ -803,6 +803,30 @@      <string name="msg_dc_trail_unknown">"Encountered trailing data of unknown type"</string>      <string name="msg_dc_unlocking">"Unlocking secret key"</string> +    <!-- Messages for SignEncrypt operation --> +    <string name="msg_se_asymmetric">"Preparing public keys for encryption"</string> +    <string name="msg_se_clearsign_only">"Signing of cleartext input not supported!"</string> +    <string name="msg_se_compressing">"Preparing compression"</string> +    <string name="msg_se_encrypting">"Encrypting data"</string> +    <string name="msg_se_error_bad_passphrase">"Bad passphrase!"</string> +    <string name="msg_se_error_io">"Encountered IO Exception during operation!"</string> +    <string name="msg_se_error_key_sign">"Selected signing key cannot sign data!"</string> +    <string name="msg_se_error_sign_key">"Error fetching signing key!"</string> +    <string name="msg_se_error_nfc">"NFC data error!"</string> +    <string name="msg_se_error_no_passphrase">"No passphrase provided!"</string> +    <string name="msg_se_error_pgp">"Internal PGP error!"</string> +    <string name="msg_se_error_sig">"Encountered PGP signature exception!"</string> +    <string name="msg_se_error_unlock">"Unknown error unlocking key!"</string> +    <string name="msg_se_key_ok">"Encrypting for key: %s"</string> +    <string name="msg_se_key_unknown">"Missing key for encryption: %s"</string> +    <string name="msg_se_key_warn">"Bad key for encryption: %s"</string> +    <string name="msg_se_ok">"Sign/Encrypt operation successful!"</string> +    <string name="msg_se_pending_nfc">"NFC token required, requesting user input…"</string> +    <string name="msg_se_signing">"Signing data (without encryption)"</string> +    <string name="msg_se_sigcrypting">"Encrypting data with signature"</string> +    <string name="msg_se">"Starting sign and/or encrypt operation"</string> +    <string name="msg_se_symmetric">"Preparing symmetric encryption"</string> +      <!-- PassphraseCache -->      <string name="passp_cache_notif_click_to_clear">"Click to clear cached passphrases"</string>      <string name="passp_cache_notif_n_keys">"OpenKeychain has cached %d passphrases"</string>  | 
