Added "RSASSA-PSS" algorithm in allowed algorithm list. (#11626)

Motivation:
While OpenSSK is provided support for the "RSASSA-PSS" algorithm this was still not valid from netty. Which was causing issue in validating certificates which was signed using this algorithm.

Modification:
Added "RSASSA-PSS" in LOCAL_SUPPORTED_SIGNATURE_ALGORITHMS.
validation:
Validated and tested with CA and User cert singed with RSASSA-PSS algorithm.

Result:
Fixes #11360

Co-authored-by: Norman Maurer <norman_maurer@apple.com>
This commit is contained in:
kushalagrawal 2021-08-31 05:45:57 +05:30 committed by GitHub
parent 95e1a21836
commit 7b8050ae53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 148 additions and 6 deletions

View File

@ -42,6 +42,7 @@ abstract class ExtendedOpenSslSession extends ExtendedSSLSession implements Open
private static final String[] LOCAL_SUPPORTED_SIGNATURE_ALGORITHMS = { private static final String[] LOCAL_SUPPORTED_SIGNATURE_ALGORITHMS = {
"SHA512withRSA", "SHA512withECDSA", "SHA384withRSA", "SHA384withECDSA", "SHA256withRSA", "SHA512withRSA", "SHA512withECDSA", "SHA384withRSA", "SHA384withECDSA", "SHA256withRSA",
"SHA256withECDSA", "SHA224withRSA", "SHA224withECDSA", "SHA1withRSA", "SHA1withECDSA", "SHA256withECDSA", "SHA224withRSA", "SHA224withECDSA", "SHA1withRSA", "SHA1withECDSA",
"RSASSA-PSS",
}; };
private final OpenSslSession wrapped; private final OpenSslSession wrapped;

View File

@ -18,6 +18,8 @@ package io.netty.handler.ssl;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLSessionContext;

View File

@ -69,8 +69,15 @@ public class ConscryptSslEngineTest extends SSLEngineTest {
} }
@Disabled("Possible Conscrypt bug") @Disabled("Possible Conscrypt bug")
@Override
public void testSessionCacheTimeout(SSLEngineTestParam param) throws Exception { public void testSessionCacheTimeout(SSLEngineTestParam param) throws Exception {
// Skip // Skip
// https://github.com/google/conscrypt/issues/851 // https://github.com/google/conscrypt/issues/851
} }
@Disabled("Not supported")
@Override
public void testRSASSAPSS(SSLEngineTestParam param) {
// skip
}
} }

View File

@ -81,8 +81,15 @@ public class JdkConscryptSslEngineInteropTest extends SSLEngineTest {
} }
@Disabled("Possible Conscrypt bug") @Disabled("Possible Conscrypt bug")
@Override
public void testSessionCacheTimeout(SSLEngineTestParam param) { public void testSessionCacheTimeout(SSLEngineTestParam param) {
// Skip // Skip
// https://github.com/google/conscrypt/issues/851 // https://github.com/google/conscrypt/issues/851
} }
@Disabled("Not supported")
@Override
public void testRSASSAPSS(SSLEngineTestParam param) {
// skip
}
} }

View File

@ -18,6 +18,8 @@ package io.netty.handler.ssl;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
import java.util.ArrayList; import java.util.ArrayList;
@ -192,6 +194,14 @@ public class JdkOpenSslEngineInteroptTest extends SSLEngineTest {
super.testSessionCacheSize(param); super.testSessionCacheSize(param);
} }
@MethodSource("newTestParams")
@ParameterizedTest
@Override
public void testRSASSAPSS(SSLEngineTestParam param) throws Exception {
checkShouldUseKeyManagerFactory();
super.testRSASSAPSS(param);
}
@Override @Override
protected SSLEngine wrapEngine(SSLEngine engine) { protected SSLEngine wrapEngine(SSLEngine engine) {
return Java8SslTestUtils.wrapSSLEngineForTesting(engine); return Java8SslTestUtils.wrapSSLEngineForTesting(engine);

View File

@ -25,6 +25,7 @@ import io.netty.internal.tcnative.SSL;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.ResourcesUtil;
import org.junit.AssumptionViolatedException; import org.junit.AssumptionViolatedException;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
@ -35,6 +36,7 @@ import org.junit.jupiter.params.provider.MethodSource;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@ -42,12 +44,14 @@ import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLParameters;
import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509ExtendedKeyManager;
import java.io.File;
import java.net.Socket; import java.net.Socket;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.AlgorithmConstraints; import java.security.AlgorithmConstraints;
import java.security.AlgorithmParameters; import java.security.AlgorithmParameters;
import java.security.CryptoPrimitive; import java.security.CryptoPrimitive;
import java.security.Key; import java.security.Key;
import java.security.KeyStore;
import java.security.Principal; import java.security.Principal;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
@ -55,6 +59,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import static io.netty.handler.ssl.OpenSslTestUtils.checkShouldUseKeyManagerFactory; import static io.netty.handler.ssl.OpenSslTestUtils.checkShouldUseKeyManagerFactory;
import static io.netty.handler.ssl.ReferenceCountedOpenSslEngine.MAX_PLAINTEXT_LENGTH; import static io.netty.handler.ssl.ReferenceCountedOpenSslEngine.MAX_PLAINTEXT_LENGTH;
@ -1559,4 +1564,12 @@ public class OpenSslEngineTest extends SSLEngineTest {
protected boolean isSessionMaybeReused(SSLEngine engine) { protected boolean isSessionMaybeReused(SSLEngine engine) {
return unwrapEngine(engine).isSessionReused(); return unwrapEngine(engine).isSessionReused();
} }
@MethodSource("newTestParams")
@ParameterizedTest
@Override
public void testRSASSAPSS(SSLEngineTestParam param) throws Exception {
checkShouldUseKeyManagerFactory();
super.testRSASSAPSS(param);
}
} }

View File

@ -17,6 +17,8 @@ package io.netty.handler.ssl;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
@ -148,6 +150,14 @@ public class OpenSslJdkSslEngineInteroptTest extends SSLEngineTest {
super.testSessionCacheSize(param); super.testSessionCacheSize(param);
} }
@MethodSource("newTestParams")
@ParameterizedTest
@Override
public void testRSASSAPSS(SSLEngineTestParam param) throws Exception {
checkShouldUseKeyManagerFactory();
super.testRSASSAPSS(param);
}
@Override @Override
protected SSLEngine wrapEngine(SSLEngine engine) { protected SSLEngine wrapEngine(SSLEngine engine) {
return Java8SslTestUtils.wrapSSLEngineForTesting(engine); return Java8SslTestUtils.wrapSSLEngineForTesting(engine);

View File

@ -780,7 +780,7 @@ public abstract class SSLEngineTest {
protected void mySetupMutualAuthServerInitSslHandler(SslHandler handler) { protected void mySetupMutualAuthServerInitSslHandler(SslHandler handler) {
} }
private void mySetupMutualAuth(final SSLEngineTestParam param, KeyManagerFactory serverKMF, protected void mySetupMutualAuth(final SSLEngineTestParam param, KeyManagerFactory serverKMF,
final File serverTrustManager, final File serverTrustManager,
KeyManagerFactory clientKMF, File clientTrustManager, KeyManagerFactory clientKMF, File clientTrustManager,
ClientAuth clientAuth, final boolean failureExpected, ClientAuth clientAuth, final boolean failureExpected,
@ -908,7 +908,7 @@ public abstract class SSLEngineTest {
clientChannel = ccf.channel(); clientChannel = ccf.channel();
} }
private static void rethrowIfNotNull(Throwable error) { protected static void rethrowIfNotNull(Throwable error) {
if (error != null) { if (error != null) {
throw new AssertionFailedError("Expected no error", error); throw new AssertionFailedError("Expected no error", error);
} }
@ -4162,6 +4162,36 @@ public abstract class SSLEngineTest {
arrayContains(serverProtocols, SslProtocols.TLS_v1_3)); arrayContains(serverProtocols, SslProtocols.TLS_v1_3));
} }
@MethodSource("newTestParams")
@ParameterizedTest
public void testRSASSAPSS(SSLEngineTestParam param) throws Exception {
char[] password = "password".toCharArray();
final KeyStore serverKeyStore = KeyStore.getInstance("PKCS12");
serverKeyStore.load(getClass().getResourceAsStream("rsaValidations-server-keystore.p12"), password);
final KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
clientKeyStore.load(getClass().getResourceAsStream("rsaValidation-user-certs.p12"), password);
final KeyManagerFactory serverKeyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
serverKeyManagerFactory.init(serverKeyStore, password);
final KeyManagerFactory clientKeyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
clientKeyManagerFactory.init(clientKeyStore, password);
File commonChain = ResourcesUtil.getFile(getClass(), "rsapss-ca-cert.cert");
ClientAuth auth = ClientAuth.REQUIRE;
mySetupMutualAuth(param, serverKeyManagerFactory, commonChain, clientKeyManagerFactory, commonChain,
auth, false, true);
assertTrue(clientLatch.await(10, TimeUnit.SECONDS));
rethrowIfNotNull(clientException);
assertTrue(serverLatch.await(5, TimeUnit.SECONDS));
rethrowIfNotNull(serverException);
}
protected SSLEngine wrapEngine(SSLEngine engine) { protected SSLEngine wrapEngine(SSLEngine engine) {
return engine; return engine;
} }

View File

@ -0,0 +1,18 @@
# Generate CA key and certificate.
openssl req -x509 -newkey rsa:2048 -days 3650 -keyout rsapss-ca-key.pem -out rsapss-ca-cert.cert -subj "/C=GB/O=Netty/OU=netty-parent/CN=west.int" -sigopt rsa_padding_mode:pss -sha256 -sigopt rsa_pss_saltlen:20
# Generate user key nand.
openssl req -newkey rsa:2048 -keyout rsapss-user-key.pem -out rsaValidation-req.pem -subj "/C=GB/O=Netty/OU=netty-parent/CN=c1" -sigopt rsa_padding_mode:pss -sha256 -sigopt rsa_pss_saltlen:20
# Sign user cert request using CA certificate.
openssl x509 -req -in rsaValidation-req.pem -days 365 -extensions ext -extfile rsapss-signing-ext.txt -CA rsapss-ca-cert.cert -CAkey rsapss-ca-key.pem -CAcreateserial -out rsapss-user-singed.cert -sigopt rsa_padding_mode:pss -sha256 -sigopt rsa_pss_saltlen:20
# Create user certificate keystore.
openssl pkcs12 -export -out rsaValidation-user-certs.p12 -inkey rsapss-user-key.pem -in rsapss-user-singed.cert
# create keystore for the
openssl pkcs12 -in rsapss-ca-cert.cert -inkey rsapss-ca-key.pem -passin pass:password -certfile rsapss-ca-cert.cert -export -out rsaValidations-server-keystore.p12 -passout pass:password -name localhost
# Create Trustore to verify the EndEntity certificate we have created.
keytool -importcert -storetype PKCS12 -keystore rsaValidations-truststore.p12 -storepass password -alias ca -file rsapss-ca-cert.cert -noprompt

View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDxTCCAoKgAwIBAgIUJ2aZ084kIATHBPDJFXVu7SJ4uVcwOAYJKoZIhvcNAQEK
MCugDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBMEcx
CzAJBgNVBAYTAkdCMQ4wDAYDVQQKDAVOZXR0eTEVMBMGA1UECwwMbmV0dHktcGFy
ZW50MREwDwYDVQQDDAh3ZXN0LmludDAeFw0yMTA4MjkwNjAxMTNaFw0zMTA4Mjcw
NjAxMTNaMEcxCzAJBgNVBAYTAkdCMQ4wDAYDVQQKDAVOZXR0eTEVMBMGA1UECwwM
bmV0dHktcGFyZW50MREwDwYDVQQDDAh3ZXN0LmludDCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAL+xcxKjWgbYHIRqnP3Sw91SNTwY85ocb+3D4xh7/F6w
cYgXwxgaHRKlk97HUzYZGFEb34BG89EOdDa1DvwxAMaN8sirefjrMLpvmfUD3Yti
kGKj+CM3gh5wFSb9mPPoY/S61+KoRSAeMKeYyFQh5IIJyVqN5mrziu0+t04X4YEw
9nATkmoS1V27Ucmo3OTkNNamqlXqVeiLKhvHtMViRGua8HwfEmjvFOTfyFHudcAz
NFFH9JR9C2g9wuokcWFD3sdFfOZ4DJVN35NrXCO4FhxxcjHOXKRdbtsucFHqCPaE
fVL0qrlkAm3pd9jKnBujC5sQbritg0uvmVuoxzy1jIUCAwEAAaNTMFEwHQYDVR0O
BBYEFAzguQlpxd/3TPhYZqEryBQ6lUdJMB8GA1UdIwQYMBaAFAzguQlpxd/3TPhY
ZqEryBQ6lUdJMA8GA1UdEwEB/wQFMAMBAf8wOAYJKoZIhvcNAQEKMCugDTALBglg
hkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBA4IBAQB3jsUwdyFO
9u/abLBGuETWbyuLX7NA9yvQL7cei40fJdsZZpZkHDJvNnrblpdaeFjuAI4vmAqz
odiHzZodSaFCwODFX8oYyBcMTHW99UYiGywskF1NnJKq13r4kP7+7w7ZaE/5YukW
VSeCXTHp1c0umuieluG87MZH4dCZgrvzpZwBeGoLLNyMyo4qHwYfkZiG2rTRpVX3
+VsWnMOaRVMYrzTB2tPZyAZyRMEfTd0fNi7ufSu6ywrOdziTu6Y1qVh18qDKpPsG
eaSCNQoO5D9vUbiFjxKPJe8hZ0bDWTbVKRpeIrQMeHXnXGPEV5rPOcJUzwnDsGqI
gqr6XlcEs+lp
-----END CERTIFICATE-----

View File

@ -0,0 +1,21 @@
[ ext ]
extendedKeyUsage = clientAuth
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
#subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
[ exts ]
extendedKeyUsage = serverAuth
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
#subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
#subjectAltName = @alt_names
[ extca ]
authorityKeyIdentifier = keyid,issuer
basicConstraints=CA:TRUE
subjectKeyIdentifier = hash
[alt_names]
DNS.1 = aws-dev-node.skylo.local