From 4a4093854dd31e453736863109645353e57dba87 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 23 Jan 2020 14:10:39 +0100 Subject: [PATCH] use upstream bouncycastle provider --- OpenKeychain/build.gradle | 8 +++--- ...DsaAuthenticationContentSignerBuilder.java | 26 ++++++++++--------- .../SessionKeySecretKeyDecryptorBuilder.java | 18 +++++++------ .../keychain/pgp/PgpKeyOperation.java | 16 +++++++----- .../keychain/pgp/PgpSignEncryptOperation.java | 2 +- .../keychain/pgp/SshPublicKey.java | 21 +++++++-------- .../keychain/pgp/UncachedKeyRing.java | 2 +- .../operations/PsoDecryptTokenOp.java | 24 +++++++++-------- .../keychain/ui/util/KeyFormattingUtils.java | 2 +- build.gradle | 9 ------- extern/bouncycastle | 2 +- gradle.properties | 3 ++- settings.gradle | 1 - 13 files changed, 68 insertions(+), 66 deletions(-) diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index 3332224f0..628e8a8e3 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -56,11 +56,13 @@ dependencies { implementation project(':openpgp-api-lib') implementation project(':nfcsweetspot') implementation project(':sshauthentication-api') - implementation project(':extern:bouncycastle:core') - implementation project(':extern:bouncycastle:pg') - implementation project(':extern:bouncycastle:prov') implementation project(':extern:MaterialChipsInput') + // implementation project(':openkeychain:extern:bouncycastle:core') + implementation 'org.bouncycastle:bcprov-jdk15on:1.65' + implementation project(':extern:bouncycastle:pg') + // implementation project(':openkeychain:extern:bouncycastle:prov') + implementation 'androidx.work:work-runtime:2.2.0' // Unit tests in the local JVM with Robolectric diff --git a/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/EdDsaAuthenticationContentSignerBuilder.java b/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/EdDsaAuthenticationContentSignerBuilder.java index 91289b478..7edabffa0 100644 --- a/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/EdDsaAuthenticationContentSignerBuilder.java +++ b/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/EdDsaAuthenticationContentSignerBuilder.java @@ -1,17 +1,19 @@ package org.bouncycastle.openpgp.operator.jcajce; -import org.bouncycastle.jcajce.provider.asymmetric.eddsa.EdDSAEngine; -import org.bouncycastle.jcajce.provider.asymmetric.eddsa.spec.EdDSANamedCurveTable; -import org.bouncycastle.jcajce.provider.asymmetric.eddsa.spec.EdDSAParameterSpec; +import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPrivateKey; import org.bouncycastle.openpgp.PGPRuntimeOperationException; import org.bouncycastle.openpgp.operator.PGPContentSigner; import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.PGPDigestCalculator; -import java.io.ByteArrayOutputStream; import java.io.OutputStream; -import java.security.*; +import java.security.InvalidKeyException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.Signature; +import java.security.SignatureException; public class EdDsaAuthenticationContentSignerBuilder implements PGPContentSignerBuilder { private JcaPGPKeyConverter keyConverter = new JcaPGPKeyConverter(); @@ -33,9 +35,8 @@ public class EdDsaAuthenticationContentSignerBuilder implements PGPContentSigner return this; } - private Signature createSignature() throws NoSuchAlgorithmException { - EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("Ed25519"); - return new EdDSAEngine(MessageDigest.getInstance(spec.getHashAlgorithm())); + private Signature createSignature() throws PGPException { + return new OperatorHelper(new DefaultJcaJceHelper()).createSignature(keyAlgorithm, hashAlgorithm); } public PGPContentSigner build(final int signatureType, final long keyID, final PrivateKey privateKey) @@ -43,12 +44,12 @@ public class EdDsaAuthenticationContentSignerBuilder implements PGPContentSigner Signature signatureEdDsa; try { signatureEdDsa = createSignature(); - } catch (NoSuchAlgorithmException e) { + } catch (PGPException e) { throw new PGPException("unable to create Signature.", e); } final Signature signature = signatureEdDsa; - final ByteArrayOutputStream dataOutputStream = new ByteArrayOutputStream(); + final PGPDigestCalculator digestCalculator = new JcaPGPDigestCalculatorProviderBuilder().build().get(hashAlgorithm); try { signature.initSign(privateKey); @@ -74,11 +75,12 @@ public class EdDsaAuthenticationContentSignerBuilder implements PGPContentSigner } public OutputStream getOutputStream() { - return new SignatureOutputStream(signature); + return digestCalculator.getOutputStream(); } public byte[] getSignature() { try { + signature.update(digestCalculator.getDigest()); return signature.sign(); } catch (SignatureException e) { throw new PGPRuntimeOperationException("Unable to create signature: " + e.getMessage(), e); @@ -86,7 +88,7 @@ public class EdDsaAuthenticationContentSignerBuilder implements PGPContentSigner } public byte[] getDigest() { - return null; + return digestCalculator.getDigest(); } }; } diff --git a/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/SessionKeySecretKeyDecryptorBuilder.java b/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/SessionKeySecretKeyDecryptorBuilder.java index 6f1b6f5ef..bf44de997 100644 --- a/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/SessionKeySecretKeyDecryptorBuilder.java +++ b/OpenKeychain/src/main/java/org/bouncycastle/openpgp/operator/jcajce/SessionKeySecretKeyDecryptorBuilder.java @@ -7,6 +7,15 @@ package org.bouncycastle.openpgp.operator.jcajce; +import org.bouncycastle.bcpg.S2K; +import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; +import org.bouncycastle.jcajce.util.NamedJcaJceHelper; +import org.bouncycastle.jcajce.util.ProviderJcaJceHelper; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPUtil; +import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; +import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; + import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Provider; @@ -15,13 +24,6 @@ import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.spec.IvParameterSpec; -import org.bouncycastle.bcpg.S2K; -import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; -import org.bouncycastle.jcajce.util.NamedJcaJceHelper; -import org.bouncycastle.jcajce.util.ProviderJcaJceHelper; -import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; -import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; /** This is a builder for a special PBESecretKeyDecryptor which is parametrized by a @@ -90,7 +92,7 @@ public class SessionKeySecretKeyDecryptorBuilder { Cipher c = helper.createCipher(PGPUtil.getSymmetricCipherName(encAlgorithm) + "/CFB/NoPadding"); - c.init(Cipher.DECRYPT_MODE, PGPUtil.makeSymmetricKey(encAlgorithm, key), new IvParameterSpec(iv)); + c.init(Cipher.DECRYPT_MODE, JcaJcePGPUtil.makeSymmetricKey(encAlgorithm, key), new IvParameterSpec(iv)); return c.doFinal(keyData, keyOff, keyLen); } 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 2533c626a..813404c43 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; @@ -46,7 +47,11 @@ import org.bouncycastle.bcpg.S2K; import org.bouncycastle.bcpg.sig.Features; import org.bouncycastle.bcpg.sig.KeyFlags; import org.bouncycastle.bcpg.sig.RevocationReasonTags; -import org.bouncycastle.jcajce.provider.asymmetric.eddsa.spec.EdDSAGenParameterSpec; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator; +import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters; +import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters; +import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters; import org.bouncycastle.jce.spec.ElGamalParameterSpec; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPKeyFlags; @@ -250,10 +255,8 @@ public class PgpKeyOperation { return null; } progress(R.string.progress_generating_eddsa, 30); - EdDSAGenParameterSpec edParamSpec = - new EdDSAGenParameterSpec("ed25519"); - keyGen = KeyPairGenerator.getInstance("EdDSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME); - keyGen.initialize(edParamSpec, new SecureRandom()); + keyGen = KeyPairGenerator.getInstance("ED25519", Constants.BOUNCY_CASTLE_PROVIDER_NAME); + keyGen.initialize(256, new SecureRandom()); algorithm = PGPPublicKey.EDDSA; break; @@ -281,7 +284,8 @@ public class PgpKeyOperation { } // build new key pair - return new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), creationTime); + KeyPair keyPair = keyGen.generateKeyPair(); + return new JcaPGPKeyPair(algorithm, keyPair, creationTime); } catch(NoSuchProviderException | InvalidAlgorithmParameterException e) { throw new RuntimeException(e); 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 855221930..80c2d2d64 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -48,10 +48,10 @@ import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPLiteralData; import org.bouncycastle.openpgp.PGPLiteralDataGenerator; import org.bouncycastle.openpgp.PGPSignatureGenerator; +import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator; import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; import org.bouncycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder; -import org.bouncycastle.openpgp.operator.jcajce.PGPUtil; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.daos.KeyRepository; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SshPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SshPublicKey.java index e711f3ca8..f6b5224d5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SshPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SshPublicKey.java @@ -19,13 +19,11 @@ package org.sufficientlysecure.keychain.pgp; import org.bouncycastle.bcpg.DSAPublicBCPGKey; import org.bouncycastle.bcpg.ECPublicBCPGKey; -import org.bouncycastle.bcpg.EdDSAPublicBCPGKey; import org.bouncycastle.bcpg.RSAPublicBCPGKey; import org.bouncycastle.openpgp.PGPPublicKey; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.ssh.key.SshDSAPublicKey; import org.sufficientlysecure.keychain.ssh.key.SshECDSAPublicKey; -import org.sufficientlysecure.keychain.ssh.key.SshEd25519PublicKey; import org.sufficientlysecure.keychain.ssh.key.SshRSAPublicKey; import org.sufficientlysecure.keychain.ssh.utils.SshUtils; @@ -48,8 +46,9 @@ public class SshPublicKey { return encodeRSAKey(key); case PGPPublicKey.ECDSA: return encodeECKey(key); - case PGPPublicKey.EDDSA: - return encodeEdDSAKey(key); + // TODO +// case PGPPublicKey.EDDSA: +// return encodeEdDSAKey(key); case PGPPublicKey.DSA: return encodeDSAKey(key); default: @@ -76,13 +75,13 @@ public class SshPublicKey { - private String encodeEdDSAKey(PGPPublicKey publicKey) { - EdDSAPublicBCPGKey publicBCPGKey = (EdDSAPublicBCPGKey) publicKey.getPublicKeyPacket().getKey(); - - SshEd25519PublicKey pubkey = new SshEd25519PublicKey(publicBCPGKey.getEdDSAEncodedPoint()); - - return pubkey.getPublicKeyBlob(); - } +// private String encodeEdDSAKey(PGPPublicKey publicKey) { +// EdDSAPublicBCPGKey publicBCPGKey = (EdDSAPublicBCPGKey) publicKey.getPublicKeyPacket().getKey(); +// +// SshEd25519PublicKey pubkey = new SshEd25519PublicKey(publicBCPGKey.getEdDSAEncodedPoint()); +// +// return pubkey.getPublicKeyBlob(); +// } private String encodeDSAKey(PGPPublicKey publicKey) { DSAPublicBCPGKey publicBCPGKey = (DSAPublicBCPGKey) publicKey.getPublicKeyPacket().getKey(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index d2ec4125f..32f0b6ece 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -672,7 +672,7 @@ public class UncachedKeyRing { } // If NO user ids remain, error out! - if (modified == null || !modified.getUserIDs().hasNext()) { + if (modified == null || !modified.getRawUserIDs().hasNext()) { log.add(LogType.MSG_KC_ERROR_NO_UID, indent); return null; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/operations/PsoDecryptTokenOp.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/operations/PsoDecryptTokenOp.java index 20cfc041d..83c8349de 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/operations/PsoDecryptTokenOp.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/operations/PsoDecryptTokenOp.java @@ -18,21 +18,12 @@ package org.sufficientlysecure.keychain.securitytoken.operations; -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; -import javax.crypto.Cipher; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.SecretKeySpec; +import org.bouncycastle.asn1.cryptlib.CryptlibObjectIdentifiers; import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X9ECParameters; -import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.jcajce.util.MessageDigestUtils; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.openpgp.PGPException; @@ -48,6 +39,16 @@ import org.sufficientlysecure.keychain.securitytoken.KeyFormat; import org.sufficientlysecure.keychain.securitytoken.ResponseApdu; import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + /** This class implements the PSO:DECIPHER operation, as specified in OpenPGP card spec / 7.2.11 (p52 in v3.0.1). * @@ -196,7 +197,8 @@ public class PsoDecryptTokenOp { } private byte[] getEcDecipherPayload(ECKeyFormat eckf, byte[] encryptedPoint) throws CardException { - if (CustomNamedCurves.CV25519.equals(eckf.getCurveOID())) { + // TODO is this the right curve? + if (CryptlibObjectIdentifiers.curvey25519.equals(eckf.getCurveOID())) { return Arrays.copyOfRange(encryptedPoint, 1, 33); } else { X9ECParameters x9Params = ECNamedCurveTable.getByOID(eckf.getCurveOID()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java index a26a3fe25..6573397a6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java @@ -39,7 +39,7 @@ import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.operator.jcajce.PGPUtil; +import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.util.encoders.Hex; import org.openintents.openpgp.OpenPgpDecryptionResult; import org.openintents.openpgp.OpenPgpSignatureResult; diff --git a/build.gradle b/build.gradle index c47803a6d..cf3346a24 100644 --- a/build.gradle +++ b/build.gradle @@ -21,15 +21,6 @@ allprojects { } } -// Ignore tests for external bouncycastle -project(':extern:bouncycastle') { - subprojects { - // Need to re-apply the plugin here otherwise the test property below can't be set. - apply plugin: 'java' - test.enabled = false - } -} - // SDK Version and Build Tools used by all subprojects // See http://tools.android.com/tech-docs/new-build-system/tips#TOC-Controlling-Android-properties-of-all-your-modules-from-the-main-project. ext { diff --git a/extern/bouncycastle b/extern/bouncycastle index c260cecf0..596f050d0 160000 --- a/extern/bouncycastle +++ b/extern/bouncycastle @@ -1 +1 @@ -Subproject commit c260cecf0b80c986e7461f63d3c12aed72d4be4d +Subproject commit 596f050d09dc1a87c09b45e822c673399f41bab1 diff --git a/gradle.properties b/gradle.properties index 5465fec0e..662fca48f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,3 @@ android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file +android.useAndroidX=true +android.jetifier.blacklist=bcprov-jdk15on diff --git a/settings.gradle b/settings.gradle index fe751bf30..3445b9694 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,7 +2,6 @@ include ':OpenKeychain' include ':nfcsweetspot' include ':extern:bouncycastle:core' include ':extern:bouncycastle:pg' -include ':extern:bouncycastle:prov' include ':extern:minidns' include ':extern:MaterialChipsInput:library'