From e1f9758b054887208091dc791ca4b6d880dfec27 Mon Sep 17 00:00:00 2001 From: Miguel Aranda Date: Wed, 8 Jul 2026 12:13:08 +0000 Subject: [PATCH] Project import generated by Copybara. PiperOrigin-RevId: 944437907 --- .../main/java/org/conscrypt/NativeSsl.java | 52 +++++- .../conscrypt/OpenSSLRSAPrivateCrtKey.java | 24 +-- .../org/conscrypt/OpenSSLRSAPrivateKey.java | 9 +- .../javax/net/ssl/SSLSocketTest.java | 66 +++++-- .../org/conscrypt/ConscryptAndroidSuite.java | 14 ++ .../ConscryptAndroidWithoutTlsSuite.java | 164 ++++++++++++++++++ .../java/org/conscrypt/NativeSslTest.java | 35 ++++ 7 files changed, 327 insertions(+), 37 deletions(-) create mode 100644 openjdk/src/test/java/org/conscrypt/ConscryptAndroidWithoutTlsSuite.java diff --git a/common/src/main/java/org/conscrypt/NativeSsl.java b/common/src/main/java/org/conscrypt/NativeSsl.java index 7fe7c49d7..31976fbc4 100644 --- a/common/src/main/java/org/conscrypt/NativeSsl.java +++ b/common/src/main/java/org/conscrypt/NativeSsl.java @@ -396,14 +396,14 @@ void initialize(String hostname, OpenSSLKey channelIdPrivateKey) throws IOExcept NativeCrypto.SSL_set1_groups(ssl, this, toBoringSslGroups(paramsNamedGroups)); } else { // Use default named group. - String namedGroupsProperty = System.getProperty("jdk.tls.namedGroups"); - if (namedGroupsProperty == null || namedGroupsProperty.isEmpty()) { - // If the property is not set or empty, use the default named groups. See: + int[] parsedNamedGroups = getParsedTlsNamedGroupsPropertyOrNull(); + if (parsedNamedGroups == null) { + // The jdk.tls.namedGroups property has not been set or is empty. We have to use the + // default named groups. See: // https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html setDefaultNamedGroups(ssl, this); } else { - int[] groups = parseNamedGroupsProperty(namedGroupsProperty); - NativeCrypto.SSL_set1_groups(ssl, this, groups); + NativeCrypto.SSL_set1_groups(ssl, this, parsedNamedGroups); } } @@ -798,4 +798,46 @@ void close() { } } } + + /** + * Returns the parsed value of the "jdk.tls.namedGroups" property. + * + *

Is null if the property is not set or empty. + */ + static synchronized int[] getParsedTlsNamedGroupsPropertyOrNull() { + try { + parseTlsNamedGroupsProperty(); + } catch (IllegalArgumentException e) { + // This may happen if the user set the property to an invalid value. + // Since the last time the property was parsed successfully. We ignore it + // and return the previously parsed value. + } + return parsedTlsNamedGroupsProperty; + } + + private static int[] parsedTlsNamedGroupsProperty = null; + private static String unparsedTlsNamedGroupsProperty = ""; + + /** + * Parses the "jdk.tls.namedGroups" property and stores the result in {@code + * parsedTlsNamedGroupsProperty}. + * + *

May throw an {@link IllegalArgumentException} if the property contains invalid values. + */ + static synchronized void parseTlsNamedGroupsProperty() { + String property = System.getProperty("jdk.tls.namedGroups"); + if (property == null || property.isEmpty()) { + parsedTlsNamedGroupsProperty = null; + unparsedTlsNamedGroupsProperty = ""; + } else { + if (!property.equals(unparsedTlsNamedGroupsProperty)) { + unparsedTlsNamedGroupsProperty = property; + parsedTlsNamedGroupsProperty = parseNamedGroupsProperty(property); + } + } + } + + static { + parseTlsNamedGroupsProperty(); + } } diff --git a/common/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java b/common/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java index ac5e5fd07..2a4f818e1 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java +++ b/common/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java @@ -217,26 +217,26 @@ public boolean equals(Object o) { RSAPrivateCrtKey other = (RSAPrivateCrtKey) o; if (getOpenSSLKey().isHardwareBacked()) { - return getModulus().equals(other.getModulus()) - && publicExponent.equals(other.getPublicExponent()); + return equalsBigInteger(getModulus(), other.getModulus()) + && equalsBigInteger(publicExponent, other.getPublicExponent()); } else { - return getModulus().equals(other.getModulus()) - && publicExponent.equals(other.getPublicExponent()) - && getPrivateExponent().equals(other.getPrivateExponent()) - && primeP.equals(other.getPrimeP()) && primeQ.equals(other.getPrimeQ()) - && primeExponentP.equals(other.getPrimeExponentP()) - && primeExponentQ.equals(other.getPrimeExponentQ()) - && crtCoefficient.equals(other.getCrtCoefficient()); + return equalsBigInteger(getModulus(), other.getModulus()) + && equalsBigInteger(publicExponent, other.getPublicExponent()) + && equalsBigInteger(getPrivateExponent(), other.getPrivateExponent()) + && equalsBigInteger(primeP, other.getPrimeP()) && equalsBigInteger(primeQ, other.getPrimeQ()) + && equalsBigInteger(primeExponentP, other.getPrimeExponentP()) + && equalsBigInteger(primeExponentQ, other.getPrimeExponentQ()) + && equalsBigInteger(crtCoefficient, other.getCrtCoefficient()); } } else if (o instanceof RSAPrivateKey) { ensureReadParams(); RSAPrivateKey other = (RSAPrivateKey) o; if (getOpenSSLKey().isHardwareBacked()) { - return getModulus().equals(other.getModulus()); + return equalsBigInteger(getModulus(), other.getModulus()); } else { - return getModulus().equals(other.getModulus()) - && getPrivateExponent().equals(other.getPrivateExponent()); + return equalsBigInteger(getModulus(), other.getModulus()) + && equalsBigInteger(getPrivateExponent(), other.getPrivateExponent()); } } diff --git a/common/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java b/common/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java index 505e1886b..b123cdddf 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java +++ b/common/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java @@ -22,6 +22,7 @@ import java.io.ObjectOutputStream; import java.math.BigInteger; import java.security.InvalidKeyException; +import java.security.MessageDigest; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.RSAKey; @@ -203,6 +204,10 @@ public final String getAlgorithm() { return "RSA"; } + boolean equalsBigInteger(BigInteger a, BigInteger b) { + return MessageDigest.isEqual(a.toByteArray(), b.toByteArray()); + } + @Override public boolean equals(Object o) { if (o == this) { @@ -218,8 +223,8 @@ public boolean equals(Object o) { ensureReadParams(); RSAPrivateKey other = (RSAPrivateKey) o; - return modulus.equals(other.getModulus()) - && privateExponent.equals(other.getPrivateExponent()); + return equalsBigInteger(modulus, other.getModulus()) + && equalsBigInteger(privateExponent, other.getPrivateExponent()); } return false; diff --git a/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketTest.java b/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketTest.java index a68160742..2bcb67c9a 100644 --- a/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketTest.java +++ b/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketTest.java @@ -1319,26 +1319,56 @@ public void handshake_namedGroupsDontIntersect_throwsException() throws Exceptio } @Test - public void handshake_namedGroupsProperty_failsIfAllValuesAreInvalid() throws Exception { + public void setNamedGroupsProperty_invalidValue_isIgnored() throws Exception { + // Set the property to a valid value. + System.setProperty("jdk.tls.namedGroups", "MLKEM1024"); + + { + TestSSLContext context = TestSSLContext.create(); + final SSLSocket client = (SSLSocket) context.clientContext.getSocketFactory().createSocket( + context.host, context.port); + final SSLSocket server = (SSLSocket) context.serverSocket.accept(); + Future s = runAsync(() -> { + server.startHandshake(); + return null; + }); + Future c = runAsync(() -> { + client.startHandshake(); + return null; + }); + s.get(); + c.get(); + assertEquals("MLKEM1024", getCurveName(client)); + assertEquals("MLKEM1024", getCurveName(server)); + client.close(); + server.close(); + context.close(); + } + + // Now, set the property to an invalid value. System.setProperty("jdk.tls.namedGroups", "invalid,invalid2"); - TestSSLContext context = TestSSLContext.create(); - final SSLSocket client = (SSLSocket) context.clientContext.getSocketFactory().createSocket( - context.host, context.port); - final SSLSocket server = (SSLSocket) context.serverSocket.accept(); - Future s = runAsync(() -> { - server.startHandshake(); - return null; - }); - Future c = runAsync(() -> { - client.startHandshake(); - return null; - }); - assertThrows(ExecutionException.class, s::get); - assertThrows(ExecutionException.class, c::get); - client.close(); - server.close(); - context.close(); + { + TestSSLContext context = TestSSLContext.create(); + final SSLSocket client = (SSLSocket) context.clientContext.getSocketFactory().createSocket( + context.host, context.port); + final SSLSocket server = (SSLSocket) context.serverSocket.accept(); + Future s = runAsync(() -> { + server.startHandshake(); + return null; + }); + Future c = runAsync(() -> { + client.startHandshake(); + return null; + }); + s.get(); + c.get(); + assertEquals("MLKEM1024", getCurveName(client)); + assertEquals("MLKEM1024", getCurveName(server)); + client.close(); + server.close(); + context.close(); + } } @Test diff --git a/openjdk/src/test/java/org/conscrypt/ConscryptAndroidSuite.java b/openjdk/src/test/java/org/conscrypt/ConscryptAndroidSuite.java index 6f99aef83..51a3a6698 100644 --- a/openjdk/src/test/java/org/conscrypt/ConscryptAndroidSuite.java +++ b/openjdk/src/test/java/org/conscrypt/ConscryptAndroidSuite.java @@ -56,7 +56,14 @@ import org.conscrypt.javax.net.ssl.KeyManagerFactoryTest; import org.conscrypt.javax.net.ssl.KeyStoreBuilderParametersTest; import org.conscrypt.javax.net.ssl.SNIHostNameTest; +import org.conscrypt.javax.net.ssl.SSLContextTest; +import org.conscrypt.javax.net.ssl.SSLEngineTest; +import org.conscrypt.javax.net.ssl.SSLEngineVersionCompatibilityTest; import org.conscrypt.javax.net.ssl.SSLParametersTest; +import org.conscrypt.javax.net.ssl.SSLServerSocketTest; +import org.conscrypt.javax.net.ssl.SSLSessionContextTest; +import org.conscrypt.javax.net.ssl.SSLSessionTest; +import org.conscrypt.javax.net.ssl.SSLSocketTest; import org.conscrypt.javax.net.ssl.X509KeyManagerTest; import org.conscrypt.metrics.CipherSuiteTest; import org.conscrypt.metrics.OptionalMethodTest; @@ -150,7 +157,14 @@ ProtocolTest.class, ScryptTest.class, SNIHostNameTest.class, + SSLContextTest.class, + SSLEngineTest.class, + SSLEngineVersionCompatibilityTest.class, SSLParametersTest.class, + SSLServerSocketTest.class, + SSLSessionContextTest.class, + SSLSessionTest.class, + SSLSocketTest.class, VeryBasicHttpServerTest.class, X509KeyManagerTest.class, }) diff --git a/openjdk/src/test/java/org/conscrypt/ConscryptAndroidWithoutTlsSuite.java b/openjdk/src/test/java/org/conscrypt/ConscryptAndroidWithoutTlsSuite.java new file mode 100644 index 000000000..2f76dde5e --- /dev/null +++ b/openjdk/src/test/java/org/conscrypt/ConscryptAndroidWithoutTlsSuite.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.conscrypt; + +import static org.conscrypt.TestUtils.getConscryptProvider; + +import org.conscrypt.ct.SerializationTest; +import org.conscrypt.ct.VerifierTest; +import org.conscrypt.java.security.AlgorithmParameterGeneratorTestDH; +import org.conscrypt.java.security.AlgorithmParameterGeneratorTestDSA; +import org.conscrypt.java.security.AlgorithmParametersPSSTest; +import org.conscrypt.java.security.AlgorithmParametersTestAES; +import org.conscrypt.java.security.AlgorithmParametersTestDES; +import org.conscrypt.java.security.AlgorithmParametersTestDESede; +import org.conscrypt.java.security.AlgorithmParametersTestDH; +import org.conscrypt.java.security.AlgorithmParametersTestDSA; +import org.conscrypt.java.security.AlgorithmParametersTestEC; +import org.conscrypt.java.security.AlgorithmParametersTestGCM; +import org.conscrypt.java.security.AlgorithmParametersTestOAEP; +import org.conscrypt.java.security.KeyFactoryTestDH; +import org.conscrypt.java.security.KeyFactoryTestDSA; +import org.conscrypt.java.security.KeyFactoryTestEC; +import org.conscrypt.java.security.KeyFactoryTestRSACrt; +import org.conscrypt.java.security.KeyPairGeneratorTest; +import org.conscrypt.java.security.KeyPairGeneratorTestDH; +import org.conscrypt.java.security.KeyPairGeneratorTestDSA; +import org.conscrypt.java.security.KeyPairGeneratorTestRSA; +import org.conscrypt.java.security.KeyPairGeneratorTestXDH; +import org.conscrypt.java.security.MessageDigestTest; +import org.conscrypt.java.security.SignatureTest; +import org.conscrypt.java.security.cert.CertificateFactoryTest; +import org.conscrypt.java.security.cert.X509CRLTest; +import org.conscrypt.java.security.cert.X509CertificateTest; +import org.conscrypt.javax.crypto.AeadCipherTest; +import org.conscrypt.javax.crypto.CipherBasicsTest; +import org.conscrypt.javax.crypto.ECDHKeyAgreementTest; +import org.conscrypt.javax.crypto.KeyGeneratorTest; +import org.conscrypt.javax.crypto.ScryptTest; +import org.conscrypt.javax.crypto.XDHKeyAgreementTest; +import org.conscrypt.javax.crypto.XdhKeyFactoryTest; +import org.conscrypt.javax.crypto.XdhKeyTest; +import org.conscrypt.javax.net.ssl.KeyManagerFactoryTest; +import org.conscrypt.javax.net.ssl.KeyStoreBuilderParametersTest; +import org.conscrypt.javax.net.ssl.SNIHostNameTest; +import org.conscrypt.javax.net.ssl.SSLParametersTest; +import org.conscrypt.javax.net.ssl.X509KeyManagerTest; +import org.conscrypt.metrics.CipherSuiteTest; +import org.conscrypt.metrics.OptionalMethodTest; +import org.conscrypt.metrics.ProtocolTest; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import java.security.Provider; +import java.security.Security; + +import tests.util.ServiceTester; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + // org.conscrypt tests + AddressUtilsTest.class, + ApplicationProtocolSelectorAdapterTest.class, + ArrayUtilsTest.class, + CertPinManagerTest.class, + ChainStrengthAnalyzerTest.class, + DuckTypedHpkeSpiTest.class, + EdDsaTest.class, + ExposedByteArrayOutputStreamTest.class, + FileClientSessionCacheTest.class, + HostnameVerifierTest.class, + HpkeContextTest.class, + HpkeContextRecipientTest.class, + HpkeContextSenderTest.class, + HpkeSuiteTest.class, + HpkeTestVectorsTest.class, + KeySpecUtilTest.class, + MlDsaTest.class, + NativeCryptoArgTest.class, + NativeCryptoTest.class, + NativeSslTest.class, + NativeRefTest.class, + NativeSslSessionTest.class, + OpenSSLKeyTest.class, + OpenSSLX509CertificateTest.class, + SSLUtilsTest.class, + SlhDsaTest.class, + TestSessionBuilderTest.class, + TrustManagerImplTest.class, + X25519Test.class, + XwingTest.class, + // org.conscrypt.ct tests + VerifierTest.class, + SerializationTest.class, + // java.security tests + CertificateFactoryTest.class, + X509CertificateTest.class, + X509CRLTest.class, + AlgorithmParameterGeneratorTestDH.class, + AlgorithmParameterGeneratorTestDSA.class, + AlgorithmParametersPSSTest.class, + AlgorithmParametersTestAES.class, + AlgorithmParametersTestDES.class, + AlgorithmParametersTestDESede.class, + AlgorithmParametersTestDH.class, + AlgorithmParametersTestDSA.class, + AlgorithmParametersTestEC.class, + AlgorithmParametersTestGCM.class, + AlgorithmParametersTestOAEP.class, + BufferUtilsTest.class, + CipherSuiteTest.class, + KeyFactoryTestDH.class, + KeyFactoryTestDSA.class, + KeyFactoryTestEC.class, + KeyFactoryTestRSACrt.class, + KeyPairGeneratorTest.class, + KeyPairGeneratorTestDH.class, + KeyPairGeneratorTestDSA.class, + KeyPairGeneratorTestRSA.class, + KeyPairGeneratorTestXDH.class, + MessageDigestTest.class, + SignatureTest.class, + // javax.crypto tests + AeadCipherTest.class, + CipherBasicsTest.class, + MacTest.class, + ECDHKeyAgreementTest.class, + KeyGeneratorTest.class, + XDHKeyAgreementTest.class, + XdhKeyFactoryTest.class, + XdhKeyTest.class, + // javax.net.ssl tests + KeyManagerFactoryTest.class, + KeyStoreBuilderParametersTest.class, + OptionalMethodTest.class, + ProtocolTest.class, + ScryptTest.class, + SNIHostNameTest.class, + SSLParametersTest.class, + VeryBasicHttpServerTest.class, + X509KeyManagerTest.class, +}) +public class ConscryptAndroidWithoutTlsSuite { + @BeforeClass + public static void setupStatic() throws Exception { + Provider conscryptProvider = getConscryptProvider(); + Security.insertProviderAt(conscryptProvider, 1); + ServiceTester.setProviders(new Provider[] {conscryptProvider}); + } +} diff --git a/openjdk/src/test/java/org/conscrypt/NativeSslTest.java b/openjdk/src/test/java/org/conscrypt/NativeSslTest.java index 70aaa3356..2d22fb4bd 100644 --- a/openjdk/src/test/java/org/conscrypt/NativeSslTest.java +++ b/openjdk/src/test/java/org/conscrypt/NativeSslTest.java @@ -17,6 +17,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertNull; import org.junit.Test; import org.junit.runner.RunWith; @@ -101,4 +102,38 @@ public void parseNamedGroupsProperty_throwsIfNoKnownGroupsFound() { assertThrows(IllegalArgumentException.class, () -> NativeSsl.parseNamedGroupsProperty("Unknown,Unknown2")); } + + @Test + public void parseTlsNamedGroupsProperty_works() throws Exception { + String savedProperty = System.getProperty("jdk.tls.namedGroups"); + + // Valid values. + System.setProperty("jdk.tls.namedGroups", "P-384,X25519"); + NativeSsl.parseTlsNamedGroupsProperty(); + assertArrayEquals(new int[] {NativeConstants.NID_secp384r1, NativeConstants.NID_X25519}, + NativeSsl.getParsedTlsNamedGroupsPropertyOrNull()); + + // Property not set. + System.clearProperty("jdk.tls.namedGroups"); + NativeSsl.parseTlsNamedGroupsProperty(); + assertNull(NativeSsl.getParsedTlsNamedGroupsPropertyOrNull()); + + // Empty property. + System.setProperty("jdk.tls.namedGroups", ""); + NativeSsl.parseTlsNamedGroupsProperty(); + assertNull(NativeSsl.getParsedTlsNamedGroupsPropertyOrNull()); + + // Invalid values. + System.setProperty("jdk.tls.namedGroups", "invalid,invalid2"); + assertThrows(IllegalArgumentException.class, () -> NativeSsl.parseTlsNamedGroupsProperty()); + + // Restore the property to its original value, to make sure that the test does not + // have any side effects on other tests when setting the property. + if (savedProperty == null) { + System.clearProperty("jdk.tls.namedGroups"); + } else { + System.setProperty("jdk.tls.namedGroups", savedProperty); + } + NativeSsl.parseTlsNamedGroupsProperty(); + } }