diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp')
7 files changed, 191 insertions, 154 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 31a3925da..4aa05c9f8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -184,7 +184,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { // TODO: intersection between preferred hash algos of this key and PgpConstants.PREFERRED_HASH_ALGORITHMS // choose best algo - return PgpConstants.sPreferredHashAlgorithms; + return new ArrayList<>(); } private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java index ed4715681..9d059b58f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java @@ -30,7 +30,6 @@ import java.util.ArrayList; */ public class OpenPgpSignatureResultBuilder { // OpenPgpSignatureResult - private boolean mSignatureOnly = false; private String mPrimaryUserId; private ArrayList<String> mUserIds = new ArrayList<>(); private long mKeyId; @@ -42,10 +41,7 @@ public class OpenPgpSignatureResultBuilder { private boolean mIsSignatureKeyCertified = false; private boolean mIsKeyRevoked = false; private boolean mIsKeyExpired = false; - - public void setSignatureOnly(boolean signatureOnly) { - this.mSignatureOnly = signatureOnly; - } + private boolean mInsecure = false; public void setPrimaryUserId(String userId) { this.mPrimaryUserId = userId; @@ -63,6 +59,10 @@ public class OpenPgpSignatureResultBuilder { this.mValidSignature = validSignature; } + public void setInsecure(boolean insecure) { + this.mInsecure = insecure; + } + public void setSignatureKeyCertified(boolean isSignatureKeyCertified) { this.mIsSignatureKeyCertified = isSignatureKeyCertified; } @@ -87,6 +87,10 @@ public class OpenPgpSignatureResultBuilder { return mValidSignature; } + public boolean isInsecure() { + return mInsecure; + } + public void initValid(CanonicalizedPublicKeyRing signingRing, CanonicalizedPublicKey signingKey) { setSignatureAvailable(true); @@ -109,47 +113,50 @@ public class OpenPgpSignatureResultBuilder { } public OpenPgpSignatureResult build() { - if (mSignatureAvailable) { - OpenPgpSignatureResult result = new OpenPgpSignatureResult(); - result.setSignatureOnly(mSignatureOnly); - - // valid sig! - if (mKnownKey) { - if (mValidSignature) { - result.setKeyId(mKeyId); - result.setPrimaryUserId(mPrimaryUserId); - result.setUserIds(mUserIds); - - if (mIsKeyRevoked) { - Log.d(Constants.TAG, "SIGNATURE_KEY_REVOKED"); - result.setStatus(OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED); - } else if (mIsKeyExpired) { - Log.d(Constants.TAG, "SIGNATURE_KEY_EXPIRED"); - result.setStatus(OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED); - } else if (mIsSignatureKeyCertified) { - Log.d(Constants.TAG, "SIGNATURE_SUCCESS_CERTIFIED"); - result.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED); - } else { - Log.d(Constants.TAG, "SIGNATURE_SUCCESS_UNCERTIFIED"); - result.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED); - } - } else { - Log.d(Constants.TAG, "Error! Invalid signature."); - result.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR); - } - } else { - result.setKeyId(mKeyId); - - Log.d(Constants.TAG, "SIGNATURE_KEY_MISSING"); - result.setStatus(OpenPgpSignatureResult.SIGNATURE_KEY_MISSING); - } + OpenPgpSignatureResult result = new OpenPgpSignatureResult(); + if (!mSignatureAvailable) { + Log.d(Constants.TAG, "RESULT_NO_SIGNATURE"); + result.setResult(OpenPgpSignatureResult.RESULT_NO_SIGNATURE); return result; - } else { - Log.d(Constants.TAG, "no signature found!"); + } + + if (!mKnownKey) { + result.setKeyId(mKeyId); - return null; + Log.d(Constants.TAG, "RESULT_KEY_MISSING"); + result.setResult(OpenPgpSignatureResult.RESULT_KEY_MISSING); + return result; + } + + if (!mValidSignature) { + Log.d(Constants.TAG, "RESULT_INVALID_SIGNATURE"); + result.setResult(OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE); + return result; } + + result.setKeyId(mKeyId); + result.setPrimaryUserId(mPrimaryUserId); + result.setUserIds(mUserIds); + + if (mIsKeyRevoked) { + Log.d(Constants.TAG, "RESULT_INVALID_KEY_REVOKED"); + result.setResult(OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED); + } else if (mIsKeyExpired) { + Log.d(Constants.TAG, "RESULT_INVALID_KEY_EXPIRED"); + result.setResult(OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED); + } else if (mInsecure) { + Log.d(Constants.TAG, "RESULT_INVALID_INSECURE"); + result.setResult(OpenPgpSignatureResult.RESULT_INVALID_INSECURE); + } else if (mIsSignatureKeyCertified) { + Log.d(Constants.TAG, "RESULT_VALID_CONFIRMED"); + result.setResult(OpenPgpSignatureResult.RESULT_VALID_CONFIRMED); + } else { + Log.d(Constants.TAG, "RESULT_VALID_UNCONFIRMED"); + result.setResult(OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED); + } + + return result; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java index f739b1e6d..7c009921d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java @@ -21,51 +21,96 @@ import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; -import java.util.ArrayList; +import java.util.HashSet; +/** + * NIST requirements for 2011-2030 (http://www.keylength.com/en/4/): + * - RSA: 2048 bit + * - ECC: 224 bit + * - Symmetric: 3TDEA + * - Digital Signature (hash A): SHA-224 - SHA-512 + */ public class PgpConstants { - public static ArrayList<Integer> sPreferredSymmetricAlgorithms = new ArrayList<>(); - public static ArrayList<Integer> sPreferredHashAlgorithms = new ArrayList<>(); - public static ArrayList<Integer> sPreferredCompressionAlgorithms = new ArrayList<>(); +// public interface MIN_REQUIREMENT { +// int MIN_BITS; +// int BINDING_SIGNATURE_HASH_ALGO; // for User IDs, subkeys,... +// int SYMMETRIC_ALGO; +// } + // https://tools.ietf.org/html/rfc6637#section-13 + - // TODO: use hashmaps for contains in O(1) and intersections! + // PgpDecryptVerify: Secure Algorithms Whitelist + // all other algorithms will be rejected with OpenPgpDecryptionResult.RESULT_INSECURE + public static HashSet<Integer> sSymmetricAlgorithmsWhitelist = new HashSet<>(); + static { + sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_256); + sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_192); + sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_128); + sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.TWOFISH); + } + + // all other algorithms will be rejected with OpenPgpSignatureResult.RESULT_INVALID_INSECURE + public static HashSet<Integer> sHashAlgorithmsWhitelist = new HashSet<>(); + static { + sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA256); + sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA512); + sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA384); + sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA224); + sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA1); + sHashAlgorithmsWhitelist.add(HashAlgorithmTags.RIPEMD160); + } /* * Most preferred is first * These arrays are written as preferred algorithms into the keys on creation. * Other implementations may choose to honor this selection. - * - * These lists also define the only algorithms which are used in OpenKeychain. - * We do not support algorithms such as MD5 */ - static { - sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_256); - sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_192); - sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_128); - sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.TWOFISH); - - // NOTE: some implementations do not support SHA512, thus we choose SHA256 as default (Mailvelope?) - sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA256); - sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA512); - sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA384); - sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA224); - sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA1); - sPreferredHashAlgorithms.add(HashAlgorithmTags.RIPEMD160); - - /* - * Prefer ZIP - * "ZLIB provides no benefit over ZIP and is more malleable" - * - (OpenPGP WG mailinglist: "[openpgp] Intent to deprecate: Insecure primitives") - * BZIP2: very slow - */ - sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.ZIP); - sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.ZLIB); - sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.BZIP2); - } + public static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{ + SymmetricKeyAlgorithmTags.AES_256, + SymmetricKeyAlgorithmTags.AES_192, + SymmetricKeyAlgorithmTags.AES_128, + SymmetricKeyAlgorithmTags.TWOFISH + }; + + // NOTE: some implementations do not support SHA512, thus we choose SHA256 as default (Mailvelope?) + public static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{ + HashAlgorithmTags.SHA256, + HashAlgorithmTags.SHA512, + HashAlgorithmTags.SHA384, + HashAlgorithmTags.SHA224, + }; + + /* + * Prefer ZIP + * "ZLIB provides no benefit over ZIP and is more malleable" + * - (OpenPGP WG mailinglist: "[openpgp] Intent to deprecate: Insecure primitives") + * BZIP2: very slow + */ + public static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{ + CompressionAlgorithmTags.ZIP, + CompressionAlgorithmTags.ZLIB, + CompressionAlgorithmTags.BZIP2 + }; public static final int CERTIFY_HASH_ALGO = HashAlgorithmTags.SHA256; + + public static final int DEFAULT_SYMMETRIC_ALGORITHM = SymmetricKeyAlgorithmTags.AES_256; + public interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags { + int USE_DEFAULT = -1; + } + + public static final int DEFAULT_HASH_ALGORITHM = HashAlgorithmTags.SHA256; + public interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags { + int USE_DEFAULT = -1; + } + + public static final int DEFAULT_COMPRESSION_ALGORITHM = CompressionAlgorithmTags.ZIP; + public interface OpenKeychainCompressionAlgorithmTags extends CompressionAlgorithmTags { + int USE_DEFAULT = -1; + } + /* * Note: s2kcount is a number between 0 and 0xff that controls the * number of times to iterate the password hash before use. More @@ -87,28 +132,9 @@ public class PgpConstants { public static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x90; public static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA256; public static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256; - public static final int SECRET_KEY_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA256; + public static final int SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA256; // NOTE: only SHA1 is supported for key checksum calculations in OpenPGP, // see http://tools.ietf.org/html/rfc488 0#section-5.5.3 public static final int SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO = HashAlgorithmTags.SHA1; - public static interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags { - public static final int USE_PREFERRED = -1; - } - - public static interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags { - public static final int USE_PREFERRED = -1; - } - - public static interface OpenKeychainCompressionAlgorithmTags extends CompressionAlgorithmTags { - public static final int USE_PREFERRED = -1; - } - - public static int[] getAsArray(ArrayList<Integer> list) { - int[] array = new int[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = list.get(i); - } - return array; - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index e264b4678..d40bad3aa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -22,6 +22,7 @@ import android.content.Context; import android.support.annotation.NonNull; import android.webkit.MimeTypeMap; +import org.openintents.openpgp.OpenPgpDecryptionResult; import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; import org.spongycastle.bcpg.ArmoredInputStream; @@ -283,10 +284,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> PGPSignatureList signatureList = (PGPSignatureList) pgpF.nextObject(); PGPSignature messageSignature = signatureList.get(signatureIndex); - // these are not cleartext signatures! - // TODO: what about binary signatures? - signatureResultBuilder.setSignatureOnly(false); - // Verify signature and check binding signatures boolean validSignature = signature.verify(messageSignature); if (validSignature) { @@ -298,8 +295,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> OpenPgpSignatureResult signatureResult = signatureResultBuilder.build(); - if (signatureResult.getStatus() != OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED - && signatureResult.getStatus() != OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED) { + if (signatureResult.getResult() != OpenPgpSignatureResult.RESULT_VALID_CONFIRMED + && signatureResult.getResult() != OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED) { log.add(LogType.MSG_VL_ERROR_INTEGRITY_CHECK, indent); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } @@ -309,9 +306,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> log.add(LogType.MSG_VL_OK, indent); // Return a positive result, with metadata and verification info - DecryptVerifyResult result = - new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); + DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); result.setSignatureResult(signatureResult); + result.setDecryptionResult( + new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED)); return result; } @@ -322,6 +320,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput, InputStream in, OutputStream out, int indent) throws IOException, PGPException { + OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); + OpenPgpDecryptionResult decryptionResult = new OpenPgpDecryptionResult(); OperationLog log = new OperationLog(); log.add(LogType.MSG_DC, indent); @@ -614,15 +614,16 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1); return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } + decryptionResult.setResult(OpenPgpDecryptionResult.RESULT_ENCRYPTED); - // Warn about old encryption algorithms! - if (!PgpConstants.sPreferredSymmetricAlgorithms.contains(symmetricEncryptionAlgo)) { + // Check for insecure encryption algorithms! + if (!PgpConstants.sSymmetricAlgorithmsWhitelist.contains(symmetricEncryptionAlgo)) { log.add(LogType.MSG_DC_OLD_SYMMETRIC_ENCRYPTION_ALGO, indent + 1); + decryptionResult.setResult(OpenPgpDecryptionResult.RESULT_INSECURE); } JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear); Object dataChunk = plainFact.nextObject(); - OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); int signatureIndex = -1; CanonicalizedPublicKeyRing signingRing = null; CanonicalizedPublicKey signingKey = null; @@ -752,7 +753,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); result.setCharset(charset); - result.setDecryptMetadata(metadata); + result.setDecryptionMetadata(metadata); return result; } @@ -809,11 +810,9 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject(); PGPSignature messageSignature = signatureList.get(signatureIndex); - // these are not cleartext signatures! // TODO: what about binary signatures? - signatureResultBuilder.setSignatureOnly(false); - // Verify signature and check binding signatures + // Verify signature boolean validSignature = signature.verify(messageSignature); if (validSignature) { log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1); @@ -821,10 +820,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1); } - // Don't allow verification of old hash algorithms! - if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) { - validSignature = false; + // check for insecure hash algorithms + if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) { log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1); + signatureResultBuilder.setInsecure(true); } signatureResultBuilder.setValidSignature(validSignature); @@ -852,7 +851,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> Log.d(Constants.TAG, "MDC fail"); if (!signatureResultBuilder.isValidSignature()) { log.add(LogType.MSG_DC_ERROR_INTEGRITY_MISSING, indent); - return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); + decryptionResult.setResult(OpenPgpDecryptionResult.RESULT_INSECURE); } } @@ -861,12 +860,12 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> log.add(LogType.MSG_DC_OK, indent); // Return a positive result, with metadata and verification info - DecryptVerifyResult result = - new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); + DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); result.setCachedCryptoInputParcel(cryptoInput); - result.setDecryptMetadata(metadata); result.setSignatureResult(signatureResultBuilder.build()); result.setCharset(charset); + result.setDecryptionResult(decryptionResult); + result.setDecryptionMetadata(metadata); return result; } @@ -885,8 +884,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> OperationLog log = new OperationLog(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); - // cleartext signatures are never encrypted ;) - signatureResultBuilder.setSignatureOnly(true); ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -956,10 +953,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1); } - // Don't allow verification of old hash algorithms! - if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) { - validSignature = false; + // check for insecure hash algorithms + if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) { log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1); + signatureResultBuilder.setInsecure(true); } signatureResultBuilder.setValidSignature(validSignature); @@ -981,8 +978,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> clearText.length); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); - result.setDecryptMetadata(metadata); result.setSignatureResult(signatureResultBuilder.build()); + result.setDecryptionResult( + new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED)); + result.setDecryptionMetadata(metadata); return result; } @@ -994,8 +993,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> OperationLog log = new OperationLog(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); - // detached signatures are never encrypted - signatureResultBuilder.setSignatureOnly(true); updateProgress(R.string.progress_processing_signature, 0, 100); InputStream detachedSigIn = new ByteArrayInputStream(input.getDetachedSignature()); @@ -1050,9 +1047,6 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> updateProgress(R.string.progress_verifying_signature, 90, 100); log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent); - // these are not cleartext signatures! - signatureResultBuilder.setSignatureOnly(false); - // Verify signature and check binding signatures boolean validSignature = signature.verify(); if (validSignature) { @@ -1061,10 +1055,10 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1); } - // Don't allow verification of old hash algorithms! - if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) { - validSignature = false; + // check for insecure hash algorithms + if (!PgpConstants.sHashAlgorithmsWhitelist.contains(signature.getHashAlgorithm())) { log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1); + signatureResultBuilder.setInsecure(true); } signatureResultBuilder.setValidSignature(validSignature); @@ -1076,6 +1070,8 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); result.setSignatureResult(signatureResultBuilder.build()); + result.setDecryptionResult( + new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED)); return result; } 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 c82cbce8f..a7eead939 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -1206,7 +1206,7 @@ public class PgpKeyOperation { // add packet with EMPTY notation data (updates old one, but will be stripped later) PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( masterPrivateKey.getPublicKeyPacket().getAlgorithm(), - PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) + PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); { // set subpackets @@ -1233,7 +1233,7 @@ public class PgpKeyOperation { // add packet with "pin" notation data PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( masterPrivateKey.getPublicKeyPacket().getAlgorithm(), - PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) + PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); { // set subpackets @@ -1440,13 +1440,13 @@ public class PgpKeyOperation { if (divertToCard) { // use synchronous "NFC based" SignerBuilder builder = new NfcSyncPGPContentSignerBuilder( - pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO, + pKey.getAlgorithm(), PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO, pKey.getKeyID(), cryptoInput.getCryptoData()) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); } else { // content signer based on signing key algorithm and chosen hash algorithm builder = new JcaPGPContentSignerBuilder( - pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) + pKey.getAlgorithm(), PgpConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); } @@ -1472,11 +1472,11 @@ public class PgpKeyOperation { */ /* non-critical subpackets: */ hashedPacketsGen.setPreferredSymmetricAlgorithms(false, - PgpConstants.getAsArray(PgpConstants.sPreferredSymmetricAlgorithms)); + PgpConstants.PREFERRED_SYMMETRIC_ALGORITHMS); hashedPacketsGen.setPreferredHashAlgorithms(false, - PgpConstants.getAsArray(PgpConstants.sPreferredHashAlgorithms)); + PgpConstants.PREFERRED_HASH_ALGORITHMS); hashedPacketsGen.setPreferredCompressionAlgorithms(false, - PgpConstants.getAsArray(PgpConstants.sPreferredCompressionAlgorithms)); + PgpConstants.PREFERRED_COMPRESSION_ALGORITHMS); hashedPacketsGen.setPrimaryUserID(false, primary); /* critical subpackets: we consider those important for a modern pgp implementation */ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java index fa6268758..44e4b9221 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java @@ -30,13 +30,13 @@ public class PgpSignEncryptInputParcel implements Parcelable { protected String mVersionHeader = null; protected boolean mEnableAsciiArmorOutput = false; - protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED; + protected int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED; protected long[] mEncryptionMasterKeyIds = null; protected Passphrase mSymmetricPassphrase = null; - protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED; + protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT; protected long mSignatureMasterKeyId = Constants.key.none; protected Long mSignatureSubKeyId = null; - protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED; + protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT; protected long mAdditionalEncryptId = Constants.key.none; protected boolean mFailOnMissingEncryptionKeyIds = false; protected String mCharset; @@ -55,7 +55,7 @@ public class PgpSignEncryptInputParcel implements Parcelable { // 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(); + mCompressionAlgorithm = source.readInt(); mEncryptionMasterKeyIds = source.createLongArray(); mSymmetricPassphrase = source.readParcelable(loader); mSymmetricEncryptionAlgorithm = source.readInt(); @@ -79,7 +79,7 @@ public class PgpSignEncryptInputParcel implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeString(mVersionHeader); dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0); - dest.writeInt(mCompressionId); + dest.writeInt(mCompressionAlgorithm); dest.writeLongArray(mEncryptionMasterKeyIds); dest.writeParcelable(mSymmetricPassphrase, 0); dest.writeInt(mSymmetricEncryptionAlgorithm); @@ -174,12 +174,12 @@ public class PgpSignEncryptInputParcel implements Parcelable { return this; } - public int getCompressionId() { - return mCompressionId; + public int getCompressionAlgorithm() { + return mCompressionAlgorithm; } - public PgpSignEncryptInputParcel setCompressionId(int compressionId) { - mCompressionId = compressionId; + public PgpSignEncryptInputParcel setCompressionAlgorithm(int compressionAlgorithm) { + mCompressionAlgorithm = compressionAlgorithm; return this; } 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 8fb41a909..a2c5fa30d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -124,7 +124,7 @@ public class PgpSignEncryptOperation extends BaseOperation { boolean enableSignature = input.getSignatureMasterKeyId() != Constants.key.none; boolean enableEncryption = ((input.getEncryptionMasterKeyIds() != null && input.getEncryptionMasterKeyIds().length > 0) || input.getSymmetricPassphrase() != null); - boolean enableCompression = (input.getCompressionId() != CompressionAlgorithmTags.UNCOMPRESSED); + boolean enableCompression = (input.getCompressionAlgorithm() != CompressionAlgorithmTags.UNCOMPRESSED); Log.d(Constants.TAG, "enableSignature:" + enableSignature + "\nenableEncryption:" + enableEncryption @@ -229,9 +229,11 @@ public class PgpSignEncryptOperation extends BaseOperation { // Use preferred hash algo int requestedAlgorithm = input.getSignatureHashAlgorithm(); ArrayList<Integer> supported = signingKey.getSupportedHashAlgorithms(); - if (requestedAlgorithm == PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) { + if (requestedAlgorithm == PgpConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) { + input.setSignatureHashAlgorithm(PgpConstants.DEFAULT_HASH_ALGORITHM); + // TODO // get most preferred - input.setSignatureHashAlgorithm(supported.get(0)); +// input.setSignatureHashAlgorithm(supported.get(0)); } else if (!supported.contains(requestedAlgorithm)) { log.add(LogType.MSG_PSE_ERROR_HASH_ALGO, indent); return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); @@ -245,10 +247,10 @@ public class PgpSignEncryptOperation extends BaseOperation { // Use preferred encryption algo int algo = input.getSymmetricEncryptionAlgorithm(); - if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) { + if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) { // get most preferred // TODO: get from recipients - algo = PgpConstants.sPreferredSymmetricAlgorithms.get(0); + algo = PgpConstants.DEFAULT_SYMMETRIC_ALGORITHM; } // has Integrity packet enabled! JcePGPDataEncryptorBuilder encryptorBuilder = @@ -341,7 +343,13 @@ public class PgpSignEncryptOperation extends BaseOperation { if (enableCompression) { log.add(LogType.MSG_PSE_COMPRESSING, indent); - compressGen = new PGPCompressedDataGenerator(input.getCompressionId()); + + // Use preferred compression algo + int algo = input.getCompressionAlgorithm(); + if (algo == PgpConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) { + algo = PgpConstants.DEFAULT_COMPRESSION_ALGORITHM; + } + compressGen = new PGPCompressedDataGenerator(algo); bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut)); } else { bcpgOut = new BCPGOutputStream(encryptionOut); @@ -464,7 +472,7 @@ public class PgpSignEncryptOperation extends BaseOperation { InputStream in = inputData.getInputStream(); if (enableCompression) { - compressGen = new PGPCompressedDataGenerator(input.getCompressionId()); + compressGen = new PGPCompressedDataGenerator(input.getCompressionAlgorithm()); bcpgOut = new BCPGOutputStream(compressGen.open(out)); } else { bcpgOut = new BCPGOutputStream(out); |