From b6256bc92cb1d28c7cca03988dfee64d51fa9d75 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Tue, 19 May 2026 19:33:29 +0200 Subject: [PATCH 1/8] Backport 7b3ad8bff951b9f1d7a2bbe6d54e960321b2760c 8249159: Downport test rework for SSLSocketTemplate from 8224650 --- .../net/ssl/templates/SSLSocketTemplate.java | 789 ++++++++++-------- 1 file changed, 438 insertions(+), 351 deletions(-) diff --git a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java index 9e09a0e35e4..2079837412c 100644 --- a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java +++ b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java @@ -130,10 +130,7 @@ protected void runClientApplication(int serverPort) throws Exception { * Create an instance of SSLContext for client use. */ protected SSLContext createClientSSLContext() throws Exception { - return createSSLContext(trustedCertStrs, - endEntityCertStrs, endEntityPrivateKeys, - endEntityPrivateKeyAlgs, - endEntityPrivateKeyNames, + return createSSLContext(TRUSTED_CERTS, END_ENTITY_CERTS, getClientContextParameters()); } @@ -141,10 +138,7 @@ protected SSLContext createClientSSLContext() throws Exception { * Create an instance of SSLContext for server use. */ protected SSLContext createServerSSLContext() throws Exception { - return createSSLContext(trustedCertStrs, - endEntityCertStrs, endEntityPrivateKeys, - endEntityPrivateKeyAlgs, - endEntityPrivateKeyNames, + return createSSLContext(TRUSTED_CERTS, END_ENTITY_CERTS, getServerContextParameters()); } @@ -361,330 +355,24 @@ private void doClientSide() throws Exception { * Certificates and keys used in the test. */ // Trusted certificates. - private final static String[] trustedCertStrs = { - // SHA256withECDSA, curve prime256v1 - // Validity - // Not Before: May 22 07:18:16 2018 GMT - // Not After : May 17 07:18:16 2038 GMT - // Subject Key Identifier: - // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 - "-----BEGIN CERTIFICATE-----\n" + - "MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + - "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + - "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" + - "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" + - "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" + - "LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" + - "A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" + - "MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" + - "6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" + - "2YEHlSQUAbwwqCDEVB5KxaqP\n" + - "-----END CERTIFICATE-----", - // -----BEGIN PRIVATE KEY----- - // MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/HcHdoLJCdq3haVd - // XZTSKP00YzM3xX97l98vGL/RI1KhRANCAAQc9VnlW+oDNpofOc90Jb2gf5ddW+Yd - // LyyM5pAtwypVbpGU/pbR9hKtaBJKV7n+0JmzNIm61ILY7Fh95lC35nFp - // -----END PRIVATE KEY----- - - // SHA256withRSA, 2048 bits - // Validity - // Not Before: May 22 07:18:16 2018 GMT - // Not After : May 17 07:18:16 2038 GMT - // Subject Key Identifier: - // 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C - "-----BEGIN CERTIFICATE-----\n" + - "MIIDSTCCAjGgAwIBAgIJAI4ZF3iy8zG+MA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" + - "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" + - "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYT\n" + - "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + - "ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpMcY7aWieXDEM1/YJf\n" + - "JW27b4nRIFZyEYhEloyGsKTuQiiQjc8cqRZFNXe2vwziDB4IyTEl0Hjl5QF6ZaQE\n" + - "huPzzwvQm1pv64KrRXrmj3FisQK8B5OWLty9xp6xDqsaMRoyObLK+oIb20T5fSlE\n" + - "evmo1vYjnh8CX0Yzx5Gr5ye6YSEHQvYOWEws8ad17OlyToR2KMeC8w4qo6rs59pW\n" + - "g7Mxn9vo22ImDzrtAbTbXbCias3xlE0Bp0h5luyf+5U4UgksoL9B9r2oP4GrLNEV\n" + - "oJk57t8lwaR0upiv3CnS8LcJELpegZub5ggqLY8ZPYFQPjlK6IzLOm6rXPgZiZ3m\n" + - "RL0CAwEAAaNQME4wHQYDVR0OBBYEFA3dk8n+S701t+iZeJD721o92xVMMB8GA1Ud\n" + - "IwQYMBaAFA3dk8n+S701t+iZeJD721o92xVMMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" + - "hvcNAQELBQADggEBAJTRC3rKUUhVH07/1+stUungSYgpM08dY4utJq0BDk36BbmO\n" + - "0AnLDMbkwFdHEoqF6hQIfpm7SQTmXk0Fss6Eejm8ynYr6+EXiRAsaXOGOBCzF918\n" + - "/RuKOzqABfgSU4UBKECLM5bMfQTL60qx+HdbdVIpnikHZOFfmjCDVxoHsGyXc1LW\n" + - "Jhkht8IGOgc4PMGvyzTtRFjz01kvrVQZ75aN2E0GQv6dCxaEY0i3ypSzjUWAKqDh\n" + - "3e2OLwUSvumcdaxyCdZAOUsN6pDBQ+8VRG7KxnlRlY1SMEk46QgQYLbPDe/+W/yH\n" + - "ca4PejicPeh+9xRAwoTpiE2gulfT7Lm+fVM7Ruc=\n" + - "-----END CERTIFICATE-----", - // -----BEGIN PRIVATE KEY----- - // MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6THGO2lonlwxD - // Nf2CXyVtu2+J0SBWchGIRJaMhrCk7kIokI3PHKkWRTV3tr8M4gweCMkxJdB45eUB - // emWkBIbj888L0Jtab+uCq0V65o9xYrECvAeTli7cvcaesQ6rGjEaMjmyyvqCG9tE - // +X0pRHr5qNb2I54fAl9GM8eRq+cnumEhB0L2DlhMLPGndezpck6EdijHgvMOKqOq - // 7OfaVoOzMZ/b6NtiJg867QG0212womrN8ZRNAadIeZbsn/uVOFIJLKC/Qfa9qD+B - // qyzRFaCZOe7fJcGkdLqYr9wp0vC3CRC6XoGbm+YIKi2PGT2BUD45SuiMyzpuq1z4 - // GYmd5kS9AgMBAAECggEAFHSoU2MuWwJ+2jJnb5U66t2V1bAcuOE1g5zkWvG/G5z9 - // rq6Qo5kmB8f5ovdx6tw3MGUOklLwnRXBG3RxDJ1iokz3AvkY1clMNsDPlDsUrQKF - // JSO4QUBQTPSZhnsyfR8XHSU+qJ8Y+ohMfzpVv95BEoCzebtXdVgxVegBlcEmVHo2 - // kMmkRN+bYNsr8eb2r+b0EpyumS39ZgKYh09+cFb78y3T6IFMGcVJTP6nlGBFkmA/ - // 25pYeCF2tSki08qtMJZQAvKfw0Kviibk7ZxRbJqmc7B1yfnOEHP6ftjuvKl2+RP/ - // +5P5f8CfIP6gtA0LwSzAqQX/hfIKrGV5j0pCqrD0kQKBgQDeNR6Xi4sXVq79lihO - // a1bSeV7r8yoQrS8x951uO+ox+UIZ1MsAULadl7zB/P0er92p198I9M/0Jth3KBuS - // zj45mucvpiiGvmQlMKMEfNq4nN7WHOu55kufPswQB2mR4J3xmwI+4fM/nl1zc82h - // De8JSazRldJXNhfx0RGFPmgzbwKBgQDWoVXrXLbCAn41oVnWB8vwY9wjt92ztDqJ - // HMFA/SUohjePep9UDq6ooHyAf/Lz6oE5NgeVpPfTDkgvrCFVKnaWdwALbYoKXT2W - // 9FlyJox6eQzrtHAacj3HJooXWuXlphKSizntfxj3LtMR9BmrmRJOfK+SxNOVJzW2 - // +MowT20EkwKBgHmpB8jdZBgxI7o//m2BI5Y1UZ1KE5vx1kc7VXzHXSBjYqeV9FeF - // 2ZZLP9POWh/1Fh4pzTmwIDODGT2UPhSQy0zq3O0fwkyT7WzXRknsuiwd53u/dejg - // iEL2NPAJvulZ2+AuiHo5Z99LK8tMeidV46xoJDDUIMgTG+UQHNGhK5gNAoGAZn/S - // Cn7SgMC0CWSvBHnguULXZO9wH1wZAFYNLL44OqwuaIUFBh2k578M9kkke7woTmwx - // HxQTjmWpr6qimIuY6q6WBN8hJ2Xz/d1fwhYKzIp20zHuv5KDUlJjbFfqpsuy3u1C - // kts5zwI7pr1ObRbDGVyOdKcu7HI3QtR5qqyjwaUCgYABo7Wq6oHva/9V34+G3Goh - // 63bYGUnRw2l5BD11yhQv8XzGGZFqZVincD8gltNThB0Dc/BI+qu3ky4YdgdZJZ7K - // z51GQGtaHEbrHS5caV79yQ8QGY5mUVH3E+VXSxuIqb6pZq2DH4sTAEFHyncddmOH - // zoXBInYwRG9KE/Bw5elhUw== - // -----END PRIVATE KEY----- - - // SHA256withDSA, 2048 bits - // Validity - // Not Before: May 22 07:18:18 2018 GMT - // Not After : May 17 07:18:18 2038 GMT - // Subject Key Identifier: - // 76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53 - "-----BEGIN CERTIFICATE-----\n" + - "MIIErjCCBFSgAwIBAgIJAOktYLNCbr02MAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" + - "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" + - "Y2UwHhcNMTgwNTIyMDcxODE4WhcNMzgwNTE3MDcxODE4WjA7MQswCQYDVQQGEwJV\n" + - "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Uw\n" + - "ggNHMIICOQYHKoZIzjgEATCCAiwCggEBAO5GyPhSm0ze3LSu+gicdULLj05iOfTL\n" + - "UvZQ29sYz41zmqrLBQbdKiHqgJu2Re9sgTb5suLNjF047TOLPnU3jhPtWm2X8Xzi\n" + - "VGIcHym/Q/MeZxStt/88seqroI3WOKzIML2GcrishT+lcGrtH36Tf1+ue2Snn3PS\n" + - "WyxygNqPjllP5uUjYmFLvAf4QLMldkd/D2VxcwsHjB8y5iUZsXezc/LEhRZS/02m\n" + - "ivqlRw3AMkq/OVe/ZtxFWsP0nsfxEGdZuaUFpppGfixxFvymrB3+J51cTt+pZBDq\n" + - "D2y0DYfc+88iCs4jwHTfcDIpLb538HBjBj2rEgtQESQmB0ooD/+wsPsCIQC1bYch\n" + - "gElNtDYL3FgpLgNSUYp7gIWv9ehaC7LO2z7biQKCAQBitvFOnDkUja8NAF7lDpOV\n" + - "b5ipQ8SicBLW3kQamxhyuyxgZyy/PojZ/oPorkqW/T/A0rhnG6MssEpAtdiwVB+c\n" + - "rBYGo3bcwmExJhdOJ6dYuKFppPWhCwKMHs9npK+lqBMl8l5j58xlcFeC7ZfGf8GY\n" + - "GkhFW0c44vEQhMMbac6ZTTP4mw+1t7xJfmDMlLEyIpTXaAAk8uoVLWzQWnR40sHi\n" + - "ybvS0u3JxQkb7/y8tOOZu8qlz/YOS7lQ6UxUGX27Ce1E0+agfPphetoRAlS1cezq\n" + - "Wa7r64Ga0nkj1kwkcRqjgTiJx0NwnUXr78VAXFhVF95+O3lfqhvdtEGtkhDGPg7N\n" + - "A4IBBgACggEBAMmSHQK0w2i+iqUjOPzn0yNEZrzepLlLeQ1tqtn0xnlv5vBAeefD\n" + - "Pm9dd3tZOjufVWP7hhEz8xPobb1CS4e3vuQiv5UBfhdPL3f3l9T7JMAKPH6C9Vve\n" + - "OQXE5eGqbjsySbcmseHoYUt1WCSnSda1opX8zchX04e7DhGfE2/L9flpYEoSt8lI\n" + - "vMNjgOwvKdW3yvPt1/eBBHYNFG5gWPv/Q5KoyCtHS03uqGm4rNc/wZTIEEfd66C+\n" + - "QRaUltjOaHmtwOdDHaNqwhYZSVOip+Mo+TfyzHFREcdHLapo7ZXqbdYkRGxRR3d+\n" + - "3DfHaraJO0OKoYlPkr3JMvM/MSGR9AnZOcejUDBOMB0GA1UdDgQWBBR2Zp73O91F\n" + - "5TvZcjw/8FQ5hjEmUzAfBgNVHSMEGDAWgBR2Zp73O91F5TvZcjw/8FQ5hjEmUzAM\n" + - "BgNVHRMEBTADAQH/MAsGCWCGSAFlAwQDAgNHADBEAiBzriYE41M2y9Hy5ppkL0Qn\n" + - "dIlNc8JhXT/PHW7GDtViagIgMko8Qoj9gDGPK3+O9E8DC3wGiiF9CObM4LN387ok\n" + - "J+g=\n" + - "-----END CERTIFICATE-----" - // -----BEGIN PRIVATE KEY----- - // MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQDuRsj4UptM3ty0rvoInHVCy49O - // Yjn0y1L2UNvbGM+Nc5qqywUG3Soh6oCbtkXvbIE2+bLizYxdOO0ziz51N44T7Vpt - // l/F84lRiHB8pv0PzHmcUrbf/PLHqq6CN1jisyDC9hnK4rIU/pXBq7R9+k39frntk - // p59z0lsscoDaj45ZT+blI2JhS7wH+ECzJXZHfw9lcXMLB4wfMuYlGbF3s3PyxIUW - // Uv9Npor6pUcNwDJKvzlXv2bcRVrD9J7H8RBnWbmlBaaaRn4scRb8pqwd/iedXE7f - // qWQQ6g9stA2H3PvPIgrOI8B033AyKS2+d/BwYwY9qxILUBEkJgdKKA//sLD7AiEA - // tW2HIYBJTbQ2C9xYKS4DUlGKe4CFr/XoWguyzts+24kCggEAYrbxTpw5FI2vDQBe - // 5Q6TlW+YqUPEonAS1t5EGpsYcrssYGcsvz6I2f6D6K5Klv0/wNK4ZxujLLBKQLXY - // sFQfnKwWBqN23MJhMSYXTienWLihaaT1oQsCjB7PZ6SvpagTJfJeY+fMZXBXgu2X - // xn/BmBpIRVtHOOLxEITDG2nOmU0z+JsPtbe8SX5gzJSxMiKU12gAJPLqFS1s0Fp0 - // eNLB4sm70tLtycUJG+/8vLTjmbvKpc/2Dku5UOlMVBl9uwntRNPmoHz6YXraEQJU - // tXHs6lmu6+uBmtJ5I9ZMJHEao4E4icdDcJ1F6+/FQFxYVRfefjt5X6ob3bRBrZIQ - // xj4OzQQjAiEAsceWOM8do4etxp2zgnoNXV8PUUyqWhz1+0srcKV7FR4= - // -----END PRIVATE KEY----- - }; + protected final static Cert[] TRUSTED_CERTS = { + Cert.CA_ECDSA_SECP256R1, + Cert.CA_RSA_2048, + Cert.CA_DSA_2048 }; // End entity certificate. - private final static String[] endEntityCertStrs = { - // SHA256withECDSA, curve prime256v1 - // Validity - // Not Before: May 22 07:18:16 2018 GMT - // Not After : May 17 07:18:16 2038 GMT - // Authority Key Identifier: - // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 - "-----BEGIN CERTIFICATE-----\n" + - "MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + - "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + - "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" + - "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" + - "MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" + - "QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" + - "xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" + - "SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" + - "1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" + - "-----END CERTIFICATE-----", - - // SHA256withRSA, 2048 bits - // Validity - // Not Before: May 22 07:18:16 2018 GMT - // Not After : May 17 07:18:16 2038 GMT - // Authority Key Identifier: - // 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C - "-----BEGIN CERTIFICATE-----\n" + - "MIIDNjCCAh6gAwIBAgIJAO2+yPcFryUTMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" + - "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" + - "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYT\n" + - "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + - "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOC\n" + - "AQ8AMIIBCgKCAQEAszfBobWfZIp8AgC6PiWDDavP65mSvgCXUGxACbxVNAfkLhNR\n" + - "QOsHriRB3X1Q3nvO9PetC6wKlvE9jlnDDj7D+1j1r1CHO7ms1fq8rfcQYdkanDtu\n" + - "4AlHo8v+SSWX16MIXFRYDj2VVHmyPtgbltcg4zGAuwT746FdLI94uXjJjq1IOr/v\n" + - "0VIlwE5ORWH5Xc+5Tj+oFWK0E4a4GHDgtKKhn2m72hN56/GkPKGkguP5NRS1qYYV\n" + - "/EFkdyQMOV8J1M7HaicSft4OL6eKjTrgo93+kHk+tv0Dc6cpVBnalX3TorG8QI6B\n" + - "cHj1XQd78oAlAC+/jF4pc0mwi0un49kdK9gRfQIDAQABoyMwITAfBgNVHSMEGDAW\n" + - "gBQN3ZPJ/ku9NbfomXiQ+9taPdsVTDANBgkqhkiG9w0BAQsFAAOCAQEApXS0nKwm\n" + - "Kp8gpmO2yG1rpd1+2wBABiMU4JZaTqmma24DQ3RzyS+V2TeRb29dl5oTUEm98uc0\n" + - "GPZvhK8z5RFr4YE17dc04nI/VaNDCw4y1NALXGs+AHkjoPjLyGbWpi1S+gfq2sNB\n" + - "Ekkjp6COb/cb9yiFXOGVls7UOIjnVZVd0r7KaPFjZhYh82/f4PA/A1SnIKd1+nfH\n" + - "2yk7mSJNC7Z3qIVDL8MM/jBVwiC3uNe5GPB2uwhd7k5LGAVN3j4HQQGB0Sz+VC1h\n" + - "92oi6xDa+YBva2fvHuCd8P50DDjxmp9CemC7rnZ5j8egj88w14X44Xjb/Fd/ApG9\n" + - "e57NnbT7KM+Grw==\n" + - "-----END CERTIFICATE-----", - - // SHA256withRSA, curv prime256v1 - // Validity - // Not Before: May 22 07:18:16 2018 GMT - // Not After : May 21 07:18:16 2028 GMT - // Authority Key Identifier: - // 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C - "-----BEGIN CERTIFICATE-----\n" + - "MIICazCCAVOgAwIBAgIJAO2+yPcFryUUMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" + - "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" + - "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0yODA1MjEwNzE4MTZaMFUxCzAJBgNVBAYT\n" + - "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + - "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" + - "AQcDQgAE59MERNTlVZ1eeps8Z3Oue5ZkgQdPtD+WIE6tj3PbIKpxGPDxvfNP959A\n" + - "yQjEK/ehWQVrCMmNoEkIzY+IIBgB06MjMCEwHwYDVR0jBBgwFoAUDd2Tyf5LvTW3\n" + - "6Jl4kPvbWj3bFUwwDQYJKoZIhvcNAQELBQADggEBAFOTVEqs70ykhZiIdrEsF1Ra\n" + - "I3B2rLvwXZk52uSltk2/bzVvewA577ZCoxQ1pL7ynkisPfBN1uVYtHjM1VA3RC+4\n" + - "+TAK78dnI7otYjWoHp5rvs4l6c/IbOspS290IlNuDUxMErEm5wxIwj+Aukx/1y68\n" + - "hOyCvHBLMY2c1LskH1MMBbDuS1aI+lnGpToi+MoYObxGcV458vxuT8+wwV8Fkpvd\n" + - "ll8IIFmeNPRv+1E+lXbES6CSNCVaZ/lFhPgdgYKleN7sfspiz50DG4dqafuEAaX5\n" + - "xaK1NWXJxTRz0ROH/IUziyuDW6jphrlgit4+3NCzp6vP9hAJQ8Vhcj0n15BKHIQ=\n" + - "-----END CERTIFICATE-----", - - // SHA256withDSA, 2048 bits - // Validity - // Not Before: May 22 07:18:20 2018 GMT - // Not After : May 17 07:18:20 2038 GMT - // Authority Key Identifier: - // 76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53 - "-----BEGIN CERTIFICATE-----\n" + - "MIIEnDCCBEGgAwIBAgIJAP/jh1qVhNVjMAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" + - "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" + - "Y2UwHhcNMTgwNTIyMDcxODIwWhcNMzgwNTE3MDcxODIwWjBVMQswCQYDVQQGEwJV\n" + - "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Ux\n" + - "GDAWBgNVBAMMD1JlZ3Jlc3Npb24gVGVzdDCCA0cwggI6BgcqhkjOOAQBMIICLQKC\n" + - "AQEAmlavgoJrMcjqWRVcDE2dmWAPREgnzQvneEDef68cprDzjSwvOs5QeFyx75ib\n" + - "ado1e6jO/rW1prCGWHDD1oA/Tn4Pk3vu0nUxzvl1qATc+aJbpUU5Op0bvp6LbCsQ\n" + - "QslV9FeRh7Eb7bP6gpc/kHCBzEgC1VCK7prccXWy+t6SMOHbND3h+UbckfSaUuaV\n" + - "sVJNTD1D6GElfRj4Nmz1BGPfSYvKorwNZEU3gXwFgtDoAcGx7tcyClLpDHfqRfw/\n" + - "7yiqLyeiP7D4hl5lMNouJWDlAdMFp0FMgS3s9VDFinIcr6VtBWMTG7+4+czHAB+3\n" + - "fvrwlqNzhBn3uFHrekN/w8fNxwIhAJo7Sae1za7IMW0Q6hE5B4b+s2B/FaKPoA4E\n" + - "jtZu13B9AoIBAQCOZqLMKfvqZWUgT0PQ3QjR7dAFdd06I9Y3+TOQzZk1+j+vw/6E\n" + - "X4vFItX4gihb/u5Q9CdmpwhVGi7bvo+7+/IKeTgoQ6f5+PSug7SrWWUQ5sPwaZui\n" + - "zXZJ5nTeZDucFc2yFx0wgnjbPwiUxZklOT7xGiOMtzOTa2koCz5KuIBL+/wPKKxm\n" + - "ypo9VoY9xfbdU6LMXZv/lpD5XTM9rYHr/vUTNkukvV6Hpm0YMEWhVZKUJiqCqTqG\n" + - "XHaleOxSw6uQWB/+TznifcC7gB48UOQjCqOKf5VuwQneJLhlhU/jhRV3xtr+hLZa\n" + - "hW1wYhVi8cjLDrZFKlgEQqhB4crnJU0mJY+tA4IBBQACggEAID0ezl00/X8mv7eb\n" + - "bzovum1+DEEP7FM57k6HZEG2N3ve4CW+0m9Cd+cWPz8wkZ+M0j/Eqa6F0IdbkXEc\n" + - "Q7CuzvUyJ57xQ3L/WCgXsiS+Bh8O4Mz7GwW22CGmHqafbVv+hKBfr8MkskO6GJUt\n" + - "SUF/CVLzB4gMIvZMH26tBP2xK+i7FeEK9kT+nGdzQSZBAhFYpEVCBplHZO24/OYq\n" + - "1DNoU327nUuXIhmsfA8N0PjiWbIZIjTPwBGr9H0LpATI7DIDNcvRRvtROP+pBU9y\n" + - "fuykPkptg9C0rCM9t06bukpOSaEz/2VIQdLE8fHYFA6pHZ6CIc2+5cfvMgTPhcjz\n" + - "W2jCt6MjMCEwHwYDVR0jBBgwFoAUdmae9zvdReU72XI8P/BUOYYxJlMwCwYJYIZI\n" + - "AWUDBAMCA0gAMEUCIQCeI5fN08b9BpOaHdc3zQNGjp24FOL/RxlBLeBAorswJgIg\n" + - "JEZ8DhYxQy1O7mmZ2UIT7op6epWMB4dENjs0qWPmcKo=\n" + - "-----END CERTIFICATE-----" - }; - - // Private key in the format of PKCS#8. - private final static String[] endEntityPrivateKeys = { - // - // EC private key related to cert endEntityCertStrs[0]. - // - "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" + - "JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" + - "59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6", - - // - // RSA private key related to cert endEntityCertStrs[1]. - // - "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzN8GhtZ9kinwC\n" + - "ALo+JYMNq8/rmZK+AJdQbEAJvFU0B+QuE1FA6weuJEHdfVDee870960LrAqW8T2O\n" + - "WcMOPsP7WPWvUIc7uazV+ryt9xBh2RqcO27gCUejy/5JJZfXowhcVFgOPZVUebI+\n" + - "2BuW1yDjMYC7BPvjoV0sj3i5eMmOrUg6v+/RUiXATk5FYfldz7lOP6gVYrQThrgY\n" + - "cOC0oqGfabvaE3nr8aQ8oaSC4/k1FLWphhX8QWR3JAw5XwnUzsdqJxJ+3g4vp4qN\n" + - "OuCj3f6QeT62/QNzpylUGdqVfdOisbxAjoFwePVdB3vygCUAL7+MXilzSbCLS6fj\n" + - "2R0r2BF9AgMBAAECggEASIkPkMCuw4WdTT44IwERus3IOIYOs2IP3BgEDyyvm4B6\n" + - "JP/iihDWKfA4zEl1Gqcni1RXMHswSglXra682J4kui02Ov+vzEeJIY37Ibn2YnP5\n" + - "ZjRT2s9GtI/S2o4hl8A/mQb2IMViFC+xKehTukhV4j5d6NPKk0XzLR7gcMjnYxwn\n" + - "l21fS6D2oM1xRG/di7sL+uLF8EXLRzfiWDNi12uQv4nwtxPKvuKhH6yzHt7YqMH0\n" + - "46pmDKDaxV4w1JdycjCb6NrCJOYZygoQobuZqOQ30UZoZsPJrtovkncFr1e+lNcO\n" + - "+aWDfOLCtTH046dEQh5oCShyXMybNlry/QHsOtHOwQKBgQDh2iIjs+FPpQy7Z3EX\n" + - "DGEvHYqPjrYO9an2KSRr1m9gzRlWYxKY46WmPKwjMerYtra0GP+TBHrgxsfO8tD2\n" + - "wUAII6sd1qup0a/Sutgf2JxVilLykd0+Ge4/Cs51tCdJ8EqDV2B6WhTewOY2EGvg\n" + - "JiKYkeNwgRX/9M9CFSAMAk0hUQKBgQDLJAartL3DoGUPjYtpJnfgGM23yAGl6G5r\n" + - "NSXDn80BiYIC1p0bG3N0xm3yAjqOtJAUj9jZbvDNbCe3GJfLARMr23legX4tRrgZ\n" + - "nEdKnAFKAKL01oM+A5/lHdkwaZI9yyv+hgSVdYzUjB8rDmzeVQzo1BT7vXypt2yV\n" + - "6O1OnUpCbQKBgA/0rzDChopv6KRcvHqaX0tK1P0rYeVQqb9ATNhpf9jg5Idb3HZ8\n" + - "rrk91BNwdVz2G5ZBpdynFl9G69rNAMJOCM4KZw5mmh4XOEq09Ivba8AHU7DbaTv3\n" + - "7QL7KnbaUWRB26HHzIMYVh0el6T+KADf8NXCiMTr+bfpfbL3dxoiF3zhAoGAbCJD\n" + - "Qse1dBs/cKYCHfkSOsI5T6kx52Tw0jS6Y4X/FOBjyqr/elyEexbdk8PH9Ar931Qr\n" + - "NKMvn8oA4iA/PRrXX7M2yi3YQrWwbkGYWYjtzrzEAdzmg+5eARKAeJrZ8/bg9l3U\n" + - "ttKaItJsDPlizn8rngy3FsJpR9aSAMK6/+wOiYkCgYEA1tZkI1rD1W9NYZtbI9BE\n" + - "qlJVFi2PBOJMKNuWdouPX3HLQ72GJSQff2BFzLTELjweVVJ0SvY4IipzpQOHQOBy\n" + - "5qh/p6izXJZh3IHtvwVBjHoEVplg1b2+I5e3jDCfqnwcQw82dW5SxOJMg1h/BD0I\n" + - "qAL3go42DYeYhu/WnECMeis=", - - // - // EC private key related to cert endEntityCertStrs[2]. - // - "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGVc7hICpmp91jbYe\n" + - "nrr8nYHD37RZP3VENY+szuA7WjuhRANCAATn0wRE1OVVnV56mzxnc657lmSBB0+0\n" + - "P5YgTq2Pc9sgqnEY8PG980/3n0DJCMQr96FZBWsIyY2gSQjNj4ggGAHT", - - // - // DSA private key related to cert endEntityCertStrs[3]. - // - "MIICZQIBADCCAjoGByqGSM44BAEwggItAoIBAQCaVq+CgmsxyOpZFVwMTZ2ZYA9E\n" + - "SCfNC+d4QN5/rxymsPONLC86zlB4XLHvmJtp2jV7qM7+tbWmsIZYcMPWgD9Ofg+T\n" + - "e+7SdTHO+XWoBNz5olulRTk6nRu+notsKxBCyVX0V5GHsRvts/qClz+QcIHMSALV\n" + - "UIrumtxxdbL63pIw4ds0PeH5RtyR9JpS5pWxUk1MPUPoYSV9GPg2bPUEY99Ji8qi\n" + - "vA1kRTeBfAWC0OgBwbHu1zIKUukMd+pF/D/vKKovJ6I/sPiGXmUw2i4lYOUB0wWn\n" + - "QUyBLez1UMWKchyvpW0FYxMbv7j5zMcAH7d++vCWo3OEGfe4Uet6Q3/Dx83HAiEA\n" + - "mjtJp7XNrsgxbRDqETkHhv6zYH8Voo+gDgSO1m7XcH0CggEBAI5moswp++plZSBP\n" + - "Q9DdCNHt0AV13Toj1jf5M5DNmTX6P6/D/oRfi8Ui1fiCKFv+7lD0J2anCFUaLtu+\n" + - "j7v78gp5OChDp/n49K6DtKtZZRDmw/Bpm6LNdknmdN5kO5wVzbIXHTCCeNs/CJTF\n" + - "mSU5PvEaI4y3M5NraSgLPkq4gEv7/A8orGbKmj1Whj3F9t1Tosxdm/+WkPldMz2t\n" + - "gev+9RM2S6S9XoembRgwRaFVkpQmKoKpOoZcdqV47FLDq5BYH/5POeJ9wLuAHjxQ\n" + - "5CMKo4p/lW7BCd4kuGWFT+OFFXfG2v6EtlqFbXBiFWLxyMsOtkUqWARCqEHhyucl\n" + - "TSYlj60EIgIgLfA75+8KcKxdN8mr6gzGjQe7jPFGG42Ejhd7Q2F4wuw=" - }; - - // Private key algorithm of endEntityPrivateKeys. - private final static String[] endEntityPrivateKeyAlgs = { - "EC", - "RSA", - "EC", - "DSA", - }; - - // Private key names of endEntityPrivateKeys. - private final static String[] endEntityPrivateKeyNames = { - "ecdsa", - "rsa", - "ec-rsa", - "dsa", - }; + protected final static Cert[] END_ENTITY_CERTS = { + Cert.EE_ECDSA_SECP256R1, + Cert.EE_RSA_2048, + Cert.EE_EC_RSA_SECP256R1, + Cert.EE_DSA_2048 }; /* * Create an instance of SSLContext with the specified trust/key materials. */ - private SSLContext createSSLContext( - String[] trustedMaterials, - String[] keyMaterialCerts, - String[] keyMaterialKeys, - String[] keyMaterialKeyAlgs, - String[] keyMaterialKeyNames, + public static SSLContext createSSLContext( + Cert[] trustedCerts, + Cert[] endEntityCerts, ContextParameters params) throws Exception { KeyStore ts = null; // trust store @@ -696,51 +384,41 @@ private SSLContext createSSLContext( // Import the trused certs. ByteArrayInputStream is; - if (trustedMaterials != null && trustedMaterials.length != 0) { + if (trustedCerts != null && trustedCerts.length != 0) { ts = KeyStore.getInstance("JKS"); ts.load(null, null); - Certificate[] trustedCert = - new Certificate[trustedMaterials.length]; - for (int i = 0; i < trustedMaterials.length; i++) { - String trustedCertStr = trustedMaterials[i]; - - is = new ByteArrayInputStream(trustedCertStr.getBytes()); + Certificate[] trustedCert = new Certificate[trustedCerts.length]; + for (int i = 0; i < trustedCerts.length; i++) { + is = new ByteArrayInputStream(trustedCerts[i].certStr.getBytes()); try { trustedCert[i] = cf.generateCertificate(is); } finally { is.close(); } - ts.setCertificateEntry("trusted-cert-" + i, trustedCert[i]); + ts.setCertificateEntry( + "trusted-cert-" + trustedCerts[i].name(), trustedCert[i]); } } // Import the key materials. - // - // Note that certification pathes bigger than one are not supported yet. - boolean hasKeyMaterials = - (keyMaterialCerts != null) && (keyMaterialCerts.length != 0) && - (keyMaterialKeys != null) && (keyMaterialKeys.length != 0) && - (keyMaterialKeyAlgs != null) && (keyMaterialKeyAlgs.length != 0) && - (keyMaterialCerts.length == keyMaterialKeys.length) && - (keyMaterialCerts.length == keyMaterialKeyAlgs.length); - if (hasKeyMaterials) { + if (endEntityCerts != null && endEntityCerts.length != 0) { ks = KeyStore.getInstance("JKS"); ks.load(null, null); - for (int i = 0; i < keyMaterialCerts.length; i++) { - String keyCertStr = keyMaterialCerts[i]; - + for (int i = 0; i < endEntityCerts.length; i++) { // generate the private key. PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( - Base64.getMimeDecoder().decode(keyMaterialKeys[i])); + Base64.getMimeDecoder().decode(endEntityCerts[i].privKeyStr)); KeyFactory kf = - KeyFactory.getInstance(keyMaterialKeyAlgs[i]); + KeyFactory.getInstance( + endEntityCerts[i].keyAlgo); PrivateKey priKey = kf.generatePrivate(priKeySpec); // generate certificate chain - is = new ByteArrayInputStream(keyCertStr.getBytes()); + is = new ByteArrayInputStream( + endEntityCerts[i].certStr.getBytes()); Certificate keyCert = null; try { keyCert = cf.generateCertificate(is); @@ -751,7 +429,7 @@ private SSLContext createSSLContext( Certificate[] chain = new Certificate[] { keyCert }; // import the key entry. - ks.setKeyEntry("cert-" + keyMaterialKeyNames[i], + ks.setKeyEntry("cert-" + endEntityCerts[i].name(), priKey, passphrase, chain); } } @@ -762,7 +440,7 @@ private SSLContext createSSLContext( tmf.init(ts); SSLContext context = SSLContext.getInstance(params.contextProtocol); - if (hasKeyMaterials && ks != null) { + if (endEntityCerts != null && endEntityCerts.length != 0 && ks != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance(params.kmAlgorithm); kmf.init(ks, passphrase); @@ -927,4 +605,413 @@ private synchronized void logException(String prefix, Throwable cause) { System.out.println(prefix + ": " + cause); cause.printStackTrace(System.out); } + + public static enum Cert { + + CA_ECDSA_SECP256R1( + "EC", + // SHA256withECDSA, curve secp256r1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Subject Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" + + "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" + + "LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" + + "A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" + + "MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" + + "6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" + + "2YEHlSQUAbwwqCDEVB5KxaqP\n" + + "-----END CERTIFICATE-----", + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/HcHdoLJCdq3haVd\n" + + "XZTSKP00YzM3xX97l98vGL/RI1KhRANCAAQc9VnlW+oDNpofOc90Jb2gf5ddW+Yd\n" + + "LyyM5pAtwypVbpGU/pbR9hKtaBJKV7n+0JmzNIm61ILY7Fh95lC35nFp"), + + CA_ECDSA_SECP384R1( + "EC", + // SHA384withECDSA, curve secp384r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Subject Key Identifier: + // 0a:93:a9:a0:bf:e7:d5:48:9d:4f:89:15:c6:51:98:80:05:51:4e:4e + "-----BEGIN CERTIFICATE-----\n" + + "MIICCDCCAY6gAwIBAgIUCpOpoL/n1UidT4kVxlGYgAVRTk4wCgYIKoZIzj0EAwMw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowOzEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENVQN1wXWFdgC6u/dDdiC\n" + + "y+WtMTF66oL/0BSm+1ZqsogamzCryawOcHgiuXgWzx5CQ3LuOC+tDFyXpGfHuCvb\n" + + "dkzxPrP5n9NrR8/uRPe5l1KOUbchviU8z9cTP+LZxnZDo1MwUTAdBgNVHQ4EFgQU\n" + + "SktSFArR1p/5mXV0kyo0RxIVa/UwHwYDVR0jBBgwFoAUSktSFArR1p/5mXV0kyo0\n" + + "RxIVa/UwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjBZvoNmq3/v\n" + + "RD2gBTyvxjS9h0rsMRLHDnvul/KWngytwGPTOBo0Y8ixQXSjdKoc3rkCMQDkiNgx\n" + + "IDxuHedmrLQKIPnVcthTmwv7//jHiqGoKofwChMo2a1P+DQdhszmeHD/ARQ=\n" + + "-----END CERTIFICATE-----", + "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDChlbt0NF8oIKODSxn2\n" + + "WXCXuJm3z78LRkzYQS3Nx5NMjei5ytkFZz4qvD4XXMWlTEyhZANiAAQ1VA3XBdYV\n" + + "2ALq790N2ILL5a0xMXrqgv/QFKb7VmqyiBqbMKvJrA5weCK5eBbPHkJDcu44L60M\n" + + "XJekZ8e4K9t2TPE+s/mf02tHz+5E97mXUo5RtyG+JTzP1xM/4tnGdkM="), + + CA_ECDSA_SECP521R1( + "EC", + // SHA512withECDSA, curve secp521r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Subject Key Identifier: + // 25:ca:68:76:6d:29:17:9b:71:78:45:2d:d4:c6:e4:5d:fe:25:ff:90 + "-----BEGIN CERTIFICATE-----\n" + + "MIICUzCCAbSgAwIBAgIUJcpodm0pF5txeEUt1MbkXf4l/5AwCgYIKoZIzj0EAwQw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowOzEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAmFD5VmB2MdyJ6k+E\n" + + "eP4JncrE65ySL07gVmFwnr8otOt3NtRAyzmviMNNXXjo5R5NqNjKP4pr92JjT0sO\n" + + "D65yngkBtH151Ev/fiKPLxkXL9GzfKdWHVhDX7Zg6DUydzukzZV2/dIyloAIqwlz\n" + + "QVKJqT7RypDufdng8hnE9YfKo6ypZiujUzBRMB0GA1UdDgQWBBRAIrxa7WqtqUCe\n" + + "HFuKREDC92spvTAfBgNVHSMEGDAWgBRAIrxa7WqtqUCeHFuKREDC92spvTAPBgNV\n" + + "HRMBAf8EBTADAQH/MAoGCCqGSM49BAMEA4GMADCBiAJCAe22iirZnODCmlpxcv57\n" + + "3g5BEE60C+dtYmTqR4DtFyDaTRQ5CFf4ZxvQPIbD+SXi5Cbrl6qtrZG0cjUihPkC\n" + + "Hi1hAkIAiEcO7nMPgQLny+GrciojfN+bZXME/dPz6KHBm/89f8Me+jawVnv6y+df\n" + + "2Sbafh1KV6ntWQtB4bK3MXV8Ym9Eg1I=\n" + + "-----END CERTIFICATE-----", + "MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAV8dZszV6+nLw3LeA\n" + + "Q+qLJLGaqyjlsQkaopCPcmoRdy1HX6AzB/YnKsPkHp/9DQN6A2JgUhFG5B0XvKSk\n" + + "BqNNuSGhgYkDgYYABACYUPlWYHYx3InqT4R4/gmdysTrnJIvTuBWYXCevyi063c2\n" + + "1EDLOa+Iw01deOjlHk2o2Mo/imv3YmNPSw4PrnKeCQG0fXnUS/9+Io8vGRcv0bN8\n" + + "p1YdWENftmDoNTJ3O6TNlXb90jKWgAirCXNBUompPtHKkO592eDyGcT1h8qjrKlm\n" + + "Kw=="), + + CA_RSA_2048( + "RSA", + // SHA256withRSA, 2048 bits + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Subject Key Identifier: + // 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C + "-----BEGIN CERTIFICATE-----\n" + + "MIIDSTCCAjGgAwIBAgIJAI4ZF3iy8zG+MA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" + + "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" + + "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpMcY7aWieXDEM1/YJf\n" + + "JW27b4nRIFZyEYhEloyGsKTuQiiQjc8cqRZFNXe2vwziDB4IyTEl0Hjl5QF6ZaQE\n" + + "huPzzwvQm1pv64KrRXrmj3FisQK8B5OWLty9xp6xDqsaMRoyObLK+oIb20T5fSlE\n" + + "evmo1vYjnh8CX0Yzx5Gr5ye6YSEHQvYOWEws8ad17OlyToR2KMeC8w4qo6rs59pW\n" + + "g7Mxn9vo22ImDzrtAbTbXbCias3xlE0Bp0h5luyf+5U4UgksoL9B9r2oP4GrLNEV\n" + + "oJk57t8lwaR0upiv3CnS8LcJELpegZub5ggqLY8ZPYFQPjlK6IzLOm6rXPgZiZ3m\n" + + "RL0CAwEAAaNQME4wHQYDVR0OBBYEFA3dk8n+S701t+iZeJD721o92xVMMB8GA1Ud\n" + + "IwQYMBaAFA3dk8n+S701t+iZeJD721o92xVMMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" + + "hvcNAQELBQADggEBAJTRC3rKUUhVH07/1+stUungSYgpM08dY4utJq0BDk36BbmO\n" + + "0AnLDMbkwFdHEoqF6hQIfpm7SQTmXk0Fss6Eejm8ynYr6+EXiRAsaXOGOBCzF918\n" + + "/RuKOzqABfgSU4UBKECLM5bMfQTL60qx+HdbdVIpnikHZOFfmjCDVxoHsGyXc1LW\n" + + "Jhkht8IGOgc4PMGvyzTtRFjz01kvrVQZ75aN2E0GQv6dCxaEY0i3ypSzjUWAKqDh\n" + + "3e2OLwUSvumcdaxyCdZAOUsN6pDBQ+8VRG7KxnlRlY1SMEk46QgQYLbPDe/+W/yH\n" + + "ca4PejicPeh+9xRAwoTpiE2gulfT7Lm+fVM7Ruc=\n" + + "-----END CERTIFICATE-----", + "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6THGO2lonlwxD\n" + + "Nf2CXyVtu2+J0SBWchGIRJaMhrCk7kIokI3PHKkWRTV3tr8M4gweCMkxJdB45eUB\n" + + "emWkBIbj888L0Jtab+uCq0V65o9xYrECvAeTli7cvcaesQ6rGjEaMjmyyvqCG9tE\n" + + "+X0pRHr5qNb2I54fAl9GM8eRq+cnumEhB0L2DlhMLPGndezpck6EdijHgvMOKqOq\n" + + "7OfaVoOzMZ/b6NtiJg867QG0212womrN8ZRNAadIeZbsn/uVOFIJLKC/Qfa9qD+B\n" + + "qyzRFaCZOe7fJcGkdLqYr9wp0vC3CRC6XoGbm+YIKi2PGT2BUD45SuiMyzpuq1z4\n" + + "GYmd5kS9AgMBAAECggEAFHSoU2MuWwJ+2jJnb5U66t2V1bAcuOE1g5zkWvG/G5z9\n" + + "rq6Qo5kmB8f5ovdx6tw3MGUOklLwnRXBG3RxDJ1iokz3AvkY1clMNsDPlDsUrQKF\n" + + "JSO4QUBQTPSZhnsyfR8XHSU+qJ8Y+ohMfzpVv95BEoCzebtXdVgxVegBlcEmVHo2\n" + + "kMmkRN+bYNsr8eb2r+b0EpyumS39ZgKYh09+cFb78y3T6IFMGcVJTP6nlGBFkmA/\n" + + "25pYeCF2tSki08qtMJZQAvKfw0Kviibk7ZxRbJqmc7B1yfnOEHP6ftjuvKl2+RP/\n" + + "+5P5f8CfIP6gtA0LwSzAqQX/hfIKrGV5j0pCqrD0kQKBgQDeNR6Xi4sXVq79lihO\n" + + "a1bSeV7r8yoQrS8x951uO+ox+UIZ1MsAULadl7zB/P0er92p198I9M/0Jth3KBuS\n" + + "zj45mucvpiiGvmQlMKMEfNq4nN7WHOu55kufPswQB2mR4J3xmwI+4fM/nl1zc82h\n" + + "De8JSazRldJXNhfx0RGFPmgzbwKBgQDWoVXrXLbCAn41oVnWB8vwY9wjt92ztDqJ\n" + + "HMFA/SUohjePep9UDq6ooHyAf/Lz6oE5NgeVpPfTDkgvrCFVKnaWdwALbYoKXT2W\n" + + "9FlyJox6eQzrtHAacj3HJooXWuXlphKSizntfxj3LtMR9BmrmRJOfK+SxNOVJzW2\n" + + "+MowT20EkwKBgHmpB8jdZBgxI7o//m2BI5Y1UZ1KE5vx1kc7VXzHXSBjYqeV9FeF\n" + + "2ZZLP9POWh/1Fh4pzTmwIDODGT2UPhSQy0zq3O0fwkyT7WzXRknsuiwd53u/dejg\n" + + "iEL2NPAJvulZ2+AuiHo5Z99LK8tMeidV46xoJDDUIMgTG+UQHNGhK5gNAoGAZn/S\n" + + "Cn7SgMC0CWSvBHnguULXZO9wH1wZAFYNLL44OqwuaIUFBh2k578M9kkke7woTmwx\n" + + "HxQTjmWpr6qimIuY6q6WBN8hJ2Xz/d1fwhYKzIp20zHuv5KDUlJjbFfqpsuy3u1C\n" + + "kts5zwI7pr1ObRbDGVyOdKcu7HI3QtR5qqyjwaUCgYABo7Wq6oHva/9V34+G3Goh\n" + + "63bYGUnRw2l5BD11yhQv8XzGGZFqZVincD8gltNThB0Dc/BI+qu3ky4YdgdZJZ7K\n" + + "z51GQGtaHEbrHS5caV79yQ8QGY5mUVH3E+VXSxuIqb6pZq2DH4sTAEFHyncddmOH\n" + + "zoXBInYwRG9KE/Bw5elhUw=="), + + CA_DSA_2048( + "DSA", + // SHA256withDSA, 2048 bits + // Validity + // Not Before: May 22 07:18:18 2018 GMT + // Not After : May 17 07:18:18 2038 GMT + // Subject Key Identifier: + // 76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53 + "-----BEGIN CERTIFICATE-----\n" + + "MIIErjCCBFSgAwIBAgIJAOktYLNCbr02MAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" + + "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" + + "Y2UwHhcNMTgwNTIyMDcxODE4WhcNMzgwNTE3MDcxODE4WjA7MQswCQYDVQQGEwJV\n" + + "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Uw\n" + + "ggNHMIICOQYHKoZIzjgEATCCAiwCggEBAO5GyPhSm0ze3LSu+gicdULLj05iOfTL\n" + + "UvZQ29sYz41zmqrLBQbdKiHqgJu2Re9sgTb5suLNjF047TOLPnU3jhPtWm2X8Xzi\n" + + "VGIcHym/Q/MeZxStt/88seqroI3WOKzIML2GcrishT+lcGrtH36Tf1+ue2Snn3PS\n" + + "WyxygNqPjllP5uUjYmFLvAf4QLMldkd/D2VxcwsHjB8y5iUZsXezc/LEhRZS/02m\n" + + "ivqlRw3AMkq/OVe/ZtxFWsP0nsfxEGdZuaUFpppGfixxFvymrB3+J51cTt+pZBDq\n" + + "D2y0DYfc+88iCs4jwHTfcDIpLb538HBjBj2rEgtQESQmB0ooD/+wsPsCIQC1bYch\n" + + "gElNtDYL3FgpLgNSUYp7gIWv9ehaC7LO2z7biQKCAQBitvFOnDkUja8NAF7lDpOV\n" + + "b5ipQ8SicBLW3kQamxhyuyxgZyy/PojZ/oPorkqW/T/A0rhnG6MssEpAtdiwVB+c\n" + + "rBYGo3bcwmExJhdOJ6dYuKFppPWhCwKMHs9npK+lqBMl8l5j58xlcFeC7ZfGf8GY\n" + + "GkhFW0c44vEQhMMbac6ZTTP4mw+1t7xJfmDMlLEyIpTXaAAk8uoVLWzQWnR40sHi\n" + + "ybvS0u3JxQkb7/y8tOOZu8qlz/YOS7lQ6UxUGX27Ce1E0+agfPphetoRAlS1cezq\n" + + "Wa7r64Ga0nkj1kwkcRqjgTiJx0NwnUXr78VAXFhVF95+O3lfqhvdtEGtkhDGPg7N\n" + + "A4IBBgACggEBAMmSHQK0w2i+iqUjOPzn0yNEZrzepLlLeQ1tqtn0xnlv5vBAeefD\n" + + "Pm9dd3tZOjufVWP7hhEz8xPobb1CS4e3vuQiv5UBfhdPL3f3l9T7JMAKPH6C9Vve\n" + + "OQXE5eGqbjsySbcmseHoYUt1WCSnSda1opX8zchX04e7DhGfE2/L9flpYEoSt8lI\n" + + "vMNjgOwvKdW3yvPt1/eBBHYNFG5gWPv/Q5KoyCtHS03uqGm4rNc/wZTIEEfd66C+\n" + + "QRaUltjOaHmtwOdDHaNqwhYZSVOip+Mo+TfyzHFREcdHLapo7ZXqbdYkRGxRR3d+\n" + + "3DfHaraJO0OKoYlPkr3JMvM/MSGR9AnZOcejUDBOMB0GA1UdDgQWBBR2Zp73O91F\n" + + "5TvZcjw/8FQ5hjEmUzAfBgNVHSMEGDAWgBR2Zp73O91F5TvZcjw/8FQ5hjEmUzAM\n" + + "BgNVHRMEBTADAQH/MAsGCWCGSAFlAwQDAgNHADBEAiBzriYE41M2y9Hy5ppkL0Qn\n" + + "dIlNc8JhXT/PHW7GDtViagIgMko8Qoj9gDGPK3+O9E8DC3wGiiF9CObM4LN387ok\n" + + "J+g=\n" + + "-----END CERTIFICATE-----", + "MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQDuRsj4UptM3ty0rvoInHVCy49O" + + "Yjn0y1L2UNvbGM+Nc5qqywUG3Soh6oCbtkXvbIE2+bLizYxdOO0ziz51N44T7Vpt" + + "l/F84lRiHB8pv0PzHmcUrbf/PLHqq6CN1jisyDC9hnK4rIU/pXBq7R9+k39frntk" + + "p59z0lsscoDaj45ZT+blI2JhS7wH+ECzJXZHfw9lcXMLB4wfMuYlGbF3s3PyxIUW" + + "Uv9Npor6pUcNwDJKvzlXv2bcRVrD9J7H8RBnWbmlBaaaRn4scRb8pqwd/iedXE7f" + + "qWQQ6g9stA2H3PvPIgrOI8B033AyKS2+d/BwYwY9qxILUBEkJgdKKA//sLD7AiEA" + + "tW2HIYBJTbQ2C9xYKS4DUlGKe4CFr/XoWguyzts+24kCggEAYrbxTpw5FI2vDQBe" + + "5Q6TlW+YqUPEonAS1t5EGpsYcrssYGcsvz6I2f6D6K5Klv0/wNK4ZxujLLBKQLXY" + + "sFQfnKwWBqN23MJhMSYXTienWLihaaT1oQsCjB7PZ6SvpagTJfJeY+fMZXBXgu2X" + + "xn/BmBpIRVtHOOLxEITDG2nOmU0z+JsPtbe8SX5gzJSxMiKU12gAJPLqFS1s0Fp0" + + "eNLB4sm70tLtycUJG+/8vLTjmbvKpc/2Dku5UOlMVBl9uwntRNPmoHz6YXraEQJU" + + "tXHs6lmu6+uBmtJ5I9ZMJHEao4E4icdDcJ1F6+/FQFxYVRfefjt5X6ob3bRBrZIQ" + + "xj4OzQQjAiEAsceWOM8do4etxp2zgnoNXV8PUUyqWhz1+0srcKV7FR4="), + + EE_ECDSA_SECP256R1( + "EC", + // SHA256withECDSA, curve secp256r1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Authority Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" + + "MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" + + "QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" + + "xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" + + "SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" + + "1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" + + "-----END CERTIFICATE-----", + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" + + "JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" + + "59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6"), + + EE_ECDSA_SECP384R1( + "EC", + // SHA384withECDSA, curve secp384r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Authority Key Identifier: + // 40:2D:AA:EE:66:AA:33:27:AD:9B:5D:52:9B:60:67:6A:2B:AD:52:D2 + "-----BEGIN CERTIFICATE-----\n" + + "MIICEjCCAZegAwIBAgIUS3F0AqAXWRg07CnbknJzxofyBQMwCgYIKoZIzj0EAwMw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowVTEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMRgwFgYDVQQDDA9SZWdyZXNzaW9uIFRlc3QwdjAQBgcqhkjOPQIB\n" + + "BgUrgQQAIgNiAARqElz8b6T07eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/w\n" + + "G8ASSevpgqgpi6EzpBZaaJxE3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEj\n" + + "iLjYmt3O0pwpklijQjBAMB0GA1UdDgQWBBRALaruZqozJ62bXVKbYGdqK61S0jAf\n" + + "BgNVHSMEGDAWgBRKS1IUCtHWn/mZdXSTKjRHEhVr9TAKBggqhkjOPQQDAwNpADBm\n" + + "AjEArVDFKf48xijN6huVUJzKCOP0zlWB5Js+DItIkZmLQuhciPLhLIB/rChf3Y4C\n" + + "xuP4AjEAmfLhQRI0O3pifpYzYSVh2G7/jHNG4eO+2dvgAcU+Lh2IIj/cpLaPFSvL\n" + + "J8FXY9Nj\n" + + "-----END CERTIFICATE-----", + "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDASuI9EtK29APXPipkc\n" + + "qDA+qwlewMjv/OcjUJ77kP1Vz62oVF9iY9SRIyFIUju8wt+hZANiAARqElz8b6T0\n" + + "7eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/wG8ASSevpgqgpi6EzpBZaaJxE\n" + + "3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEjiLjYmt3O0pwpklg="), + + EE_ECDSA_SECP521R1( + "EC", + // SHA512withECDSA, curve secp521r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Authority Key Identifier: + // 7B:AA:79:A4:49:DD:59:34:F0:86:6C:51:C7:30:F4:CE:C5:81:8A:28 + "-----BEGIN CERTIFICATE-----\n" + + "MIICXDCCAb2gAwIBAgIUck4QTsbHNqUfPxfGPJLYbedFPdswCgYIKoZIzj0EAwQw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowVTEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMRgwFgYDVQQDDA9SZWdyZXNzaW9uIFRlc3QwgZswEAYHKoZIzj0C\n" + + "AQYFK4EEACMDgYYABAGa2zDLhYQHHCLI3YBqFYJTzrnDIjzwXrxhcRTS8DYkcrjZ\n" + + "+Fih1YyNhix0sdjH+3EqElXAHHuVzn3n3hPOtQCWlQCICkErB34S0cvmtRkeW8Fi\n" + + "hrR5tvJEzEZjPSgwn81kKyhV2L70je6i7Cw884Va8bODckpgw0vTmbQb7T9dupkv\n" + + "1aNCMEAwHQYDVR0OBBYEFHuqeaRJ3Vk08IZsUccw9M7FgYooMB8GA1UdIwQYMBaA\n" + + "FEAivFrtaq2pQJ4cW4pEQML3aym9MAoGCCqGSM49BAMEA4GMADCBiAJCAb33KHdY\n" + + "WDbusORWoY8Euglpd5zsF15hJsk7wtpD5HST1/NWmdCx405w+TV6a9Gr4VPHeaIQ\n" + + "99i/+f237ALL5p6IAkIBbwwFL1vt3c/bx+niyuffQPNjly80rdC9puqAqriSiboS\n" + + "efhxjidJ9HLaIRCMEPyd6vAsC8mO8YvL1uCuEQLsiGM=\n" + + "-----END CERTIFICATE-----", + "MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIB8C/2OX2Dt9vFszzV\n" + + "hcAe0CbkMlvu9uQ/L7Vz88heuIj0rUZIPGshvgIJt1hCMT8HZxYHvDa4lbUvqjFB\n" + + "+zafvPWhgYkDgYYABAGa2zDLhYQHHCLI3YBqFYJTzrnDIjzwXrxhcRTS8DYkcrjZ\n" + + "+Fih1YyNhix0sdjH+3EqElXAHHuVzn3n3hPOtQCWlQCICkErB34S0cvmtRkeW8Fi\n" + + "hrR5tvJEzEZjPSgwn81kKyhV2L70je6i7Cw884Va8bODckpgw0vTmbQb7T9dupkv\n" + + "1Q=="), + + EE_RSA_2048( + "RSA", + // SHA256withRSA, 2048 bits + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Authority Key Identifier: + // 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C + "-----BEGIN CERTIFICATE-----\n" + + "MIIDNjCCAh6gAwIBAgIJAO2+yPcFryUTMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" + + "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" + + "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOC\n" + + "AQ8AMIIBCgKCAQEAszfBobWfZIp8AgC6PiWDDavP65mSvgCXUGxACbxVNAfkLhNR\n" + + "QOsHriRB3X1Q3nvO9PetC6wKlvE9jlnDDj7D+1j1r1CHO7ms1fq8rfcQYdkanDtu\n" + + "4AlHo8v+SSWX16MIXFRYDj2VVHmyPtgbltcg4zGAuwT746FdLI94uXjJjq1IOr/v\n" + + "0VIlwE5ORWH5Xc+5Tj+oFWK0E4a4GHDgtKKhn2m72hN56/GkPKGkguP5NRS1qYYV\n" + + "/EFkdyQMOV8J1M7HaicSft4OL6eKjTrgo93+kHk+tv0Dc6cpVBnalX3TorG8QI6B\n" + + "cHj1XQd78oAlAC+/jF4pc0mwi0un49kdK9gRfQIDAQABoyMwITAfBgNVHSMEGDAW\n" + + "gBQN3ZPJ/ku9NbfomXiQ+9taPdsVTDANBgkqhkiG9w0BAQsFAAOCAQEApXS0nKwm\n" + + "Kp8gpmO2yG1rpd1+2wBABiMU4JZaTqmma24DQ3RzyS+V2TeRb29dl5oTUEm98uc0\n" + + "GPZvhK8z5RFr4YE17dc04nI/VaNDCw4y1NALXGs+AHkjoPjLyGbWpi1S+gfq2sNB\n" + + "Ekkjp6COb/cb9yiFXOGVls7UOIjnVZVd0r7KaPFjZhYh82/f4PA/A1SnIKd1+nfH\n" + + "2yk7mSJNC7Z3qIVDL8MM/jBVwiC3uNe5GPB2uwhd7k5LGAVN3j4HQQGB0Sz+VC1h\n" + + "92oi6xDa+YBva2fvHuCd8P50DDjxmp9CemC7rnZ5j8egj88w14X44Xjb/Fd/ApG9\n" + + "e57NnbT7KM+Grw==\n" + + "-----END CERTIFICATE-----", + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzN8GhtZ9kinwC\n" + + "ALo+JYMNq8/rmZK+AJdQbEAJvFU0B+QuE1FA6weuJEHdfVDee870960LrAqW8T2O\n" + + "WcMOPsP7WPWvUIc7uazV+ryt9xBh2RqcO27gCUejy/5JJZfXowhcVFgOPZVUebI+\n" + + "2BuW1yDjMYC7BPvjoV0sj3i5eMmOrUg6v+/RUiXATk5FYfldz7lOP6gVYrQThrgY\n" + + "cOC0oqGfabvaE3nr8aQ8oaSC4/k1FLWphhX8QWR3JAw5XwnUzsdqJxJ+3g4vp4qN\n" + + "OuCj3f6QeT62/QNzpylUGdqVfdOisbxAjoFwePVdB3vygCUAL7+MXilzSbCLS6fj\n" + + "2R0r2BF9AgMBAAECggEASIkPkMCuw4WdTT44IwERus3IOIYOs2IP3BgEDyyvm4B6\n" + + "JP/iihDWKfA4zEl1Gqcni1RXMHswSglXra682J4kui02Ov+vzEeJIY37Ibn2YnP5\n" + + "ZjRT2s9GtI/S2o4hl8A/mQb2IMViFC+xKehTukhV4j5d6NPKk0XzLR7gcMjnYxwn\n" + + "l21fS6D2oM1xRG/di7sL+uLF8EXLRzfiWDNi12uQv4nwtxPKvuKhH6yzHt7YqMH0\n" + + "46pmDKDaxV4w1JdycjCb6NrCJOYZygoQobuZqOQ30UZoZsPJrtovkncFr1e+lNcO\n" + + "+aWDfOLCtTH046dEQh5oCShyXMybNlry/QHsOtHOwQKBgQDh2iIjs+FPpQy7Z3EX\n" + + "DGEvHYqPjrYO9an2KSRr1m9gzRlWYxKY46WmPKwjMerYtra0GP+TBHrgxsfO8tD2\n" + + "wUAII6sd1qup0a/Sutgf2JxVilLykd0+Ge4/Cs51tCdJ8EqDV2B6WhTewOY2EGvg\n" + + "JiKYkeNwgRX/9M9CFSAMAk0hUQKBgQDLJAartL3DoGUPjYtpJnfgGM23yAGl6G5r\n" + + "NSXDn80BiYIC1p0bG3N0xm3yAjqOtJAUj9jZbvDNbCe3GJfLARMr23legX4tRrgZ\n" + + "nEdKnAFKAKL01oM+A5/lHdkwaZI9yyv+hgSVdYzUjB8rDmzeVQzo1BT7vXypt2yV\n" + + "6O1OnUpCbQKBgA/0rzDChopv6KRcvHqaX0tK1P0rYeVQqb9ATNhpf9jg5Idb3HZ8\n" + + "rrk91BNwdVz2G5ZBpdynFl9G69rNAMJOCM4KZw5mmh4XOEq09Ivba8AHU7DbaTv3\n" + + "7QL7KnbaUWRB26HHzIMYVh0el6T+KADf8NXCiMTr+bfpfbL3dxoiF3zhAoGAbCJD\n" + + "Qse1dBs/cKYCHfkSOsI5T6kx52Tw0jS6Y4X/FOBjyqr/elyEexbdk8PH9Ar931Qr\n" + + "NKMvn8oA4iA/PRrXX7M2yi3YQrWwbkGYWYjtzrzEAdzmg+5eARKAeJrZ8/bg9l3U\n" + + "ttKaItJsDPlizn8rngy3FsJpR9aSAMK6/+wOiYkCgYEA1tZkI1rD1W9NYZtbI9BE\n" + + "qlJVFi2PBOJMKNuWdouPX3HLQ72GJSQff2BFzLTELjweVVJ0SvY4IipzpQOHQOBy\n" + + "5qh/p6izXJZh3IHtvwVBjHoEVplg1b2+I5e3jDCfqnwcQw82dW5SxOJMg1h/BD0I\n" + + "qAL3go42DYeYhu/WnECMeis="), + + EE_EC_RSA_SECP256R1( + "EC", + // SHA256withRSA, curve secp256r1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 21 07:18:16 2028 GMT + // Authority Key Identifier: + // 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C + "-----BEGIN CERTIFICATE-----\n" + + "MIICazCCAVOgAwIBAgIJAO2+yPcFryUUMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" + + "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" + + "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0yODA1MjEwNzE4MTZaMFUxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" + + "AQcDQgAE59MERNTlVZ1eeps8Z3Oue5ZkgQdPtD+WIE6tj3PbIKpxGPDxvfNP959A\n" + + "yQjEK/ehWQVrCMmNoEkIzY+IIBgB06MjMCEwHwYDVR0jBBgwFoAUDd2Tyf5LvTW3\n" + + "6Jl4kPvbWj3bFUwwDQYJKoZIhvcNAQELBQADggEBAFOTVEqs70ykhZiIdrEsF1Ra\n" + + "I3B2rLvwXZk52uSltk2/bzVvewA577ZCoxQ1pL7ynkisPfBN1uVYtHjM1VA3RC+4\n" + + "+TAK78dnI7otYjWoHp5rvs4l6c/IbOspS290IlNuDUxMErEm5wxIwj+Aukx/1y68\n" + + "hOyCvHBLMY2c1LskH1MMBbDuS1aI+lnGpToi+MoYObxGcV458vxuT8+wwV8Fkpvd\n" + + "ll8IIFmeNPRv+1E+lXbES6CSNCVaZ/lFhPgdgYKleN7sfspiz50DG4dqafuEAaX5\n" + + "xaK1NWXJxTRz0ROH/IUziyuDW6jphrlgit4+3NCzp6vP9hAJQ8Vhcj0n15BKHIQ=\n" + + "-----END CERTIFICATE-----", + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGVc7hICpmp91jbYe\n" + + "nrr8nYHD37RZP3VENY+szuA7WjuhRANCAATn0wRE1OVVnV56mzxnc657lmSBB0+0\n" + + "P5YgTq2Pc9sgqnEY8PG980/3n0DJCMQr96FZBWsIyY2gSQjNj4ggGAHT"), + + EE_DSA_2048( + "DSA", + // SHA256withDSA, 2048 bits + // Validity + // Not Before: May 22 07:18:20 2018 GMT + // Not After : May 17 07:18:20 2038 GMT + // Authority Key Identifier: + // 76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53 + "-----BEGIN CERTIFICATE-----\n" + + "MIIEnDCCBEGgAwIBAgIJAP/jh1qVhNVjMAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" + + "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" + + "Y2UwHhcNMTgwNTIyMDcxODIwWhcNMzgwNTE3MDcxODIwWjBVMQswCQYDVQQGEwJV\n" + + "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Ux\n" + + "GDAWBgNVBAMMD1JlZ3Jlc3Npb24gVGVzdDCCA0cwggI6BgcqhkjOOAQBMIICLQKC\n" + + "AQEAmlavgoJrMcjqWRVcDE2dmWAPREgnzQvneEDef68cprDzjSwvOs5QeFyx75ib\n" + + "ado1e6jO/rW1prCGWHDD1oA/Tn4Pk3vu0nUxzvl1qATc+aJbpUU5Op0bvp6LbCsQ\n" + + "QslV9FeRh7Eb7bP6gpc/kHCBzEgC1VCK7prccXWy+t6SMOHbND3h+UbckfSaUuaV\n" + + "sVJNTD1D6GElfRj4Nmz1BGPfSYvKorwNZEU3gXwFgtDoAcGx7tcyClLpDHfqRfw/\n" + + "7yiqLyeiP7D4hl5lMNouJWDlAdMFp0FMgS3s9VDFinIcr6VtBWMTG7+4+czHAB+3\n" + + "fvrwlqNzhBn3uFHrekN/w8fNxwIhAJo7Sae1za7IMW0Q6hE5B4b+s2B/FaKPoA4E\n" + + "jtZu13B9AoIBAQCOZqLMKfvqZWUgT0PQ3QjR7dAFdd06I9Y3+TOQzZk1+j+vw/6E\n" + + "X4vFItX4gihb/u5Q9CdmpwhVGi7bvo+7+/IKeTgoQ6f5+PSug7SrWWUQ5sPwaZui\n" + + "zXZJ5nTeZDucFc2yFx0wgnjbPwiUxZklOT7xGiOMtzOTa2koCz5KuIBL+/wPKKxm\n" + + "ypo9VoY9xfbdU6LMXZv/lpD5XTM9rYHr/vUTNkukvV6Hpm0YMEWhVZKUJiqCqTqG\n" + + "XHaleOxSw6uQWB/+TznifcC7gB48UOQjCqOKf5VuwQneJLhlhU/jhRV3xtr+hLZa\n" + + "hW1wYhVi8cjLDrZFKlgEQqhB4crnJU0mJY+tA4IBBQACggEAID0ezl00/X8mv7eb\n" + + "bzovum1+DEEP7FM57k6HZEG2N3ve4CW+0m9Cd+cWPz8wkZ+M0j/Eqa6F0IdbkXEc\n" + + "Q7CuzvUyJ57xQ3L/WCgXsiS+Bh8O4Mz7GwW22CGmHqafbVv+hKBfr8MkskO6GJUt\n" + + "SUF/CVLzB4gMIvZMH26tBP2xK+i7FeEK9kT+nGdzQSZBAhFYpEVCBplHZO24/OYq\n" + + "1DNoU327nUuXIhmsfA8N0PjiWbIZIjTPwBGr9H0LpATI7DIDNcvRRvtROP+pBU9y\n" + + "fuykPkptg9C0rCM9t06bukpOSaEz/2VIQdLE8fHYFA6pHZ6CIc2+5cfvMgTPhcjz\n" + + "W2jCt6MjMCEwHwYDVR0jBBgwFoAUdmae9zvdReU72XI8P/BUOYYxJlMwCwYJYIZI\n" + + "AWUDBAMCA0gAMEUCIQCeI5fN08b9BpOaHdc3zQNGjp24FOL/RxlBLeBAorswJgIg\n" + + "JEZ8DhYxQy1O7mmZ2UIT7op6epWMB4dENjs0qWPmcKo=\n" + + "-----END CERTIFICATE-----", + "MIICZQIBADCCAjoGByqGSM44BAEwggItAoIBAQCaVq+CgmsxyOpZFVwMTZ2ZYA9E\n" + + "SCfNC+d4QN5/rxymsPONLC86zlB4XLHvmJtp2jV7qM7+tbWmsIZYcMPWgD9Ofg+T\n" + + "e+7SdTHO+XWoBNz5olulRTk6nRu+notsKxBCyVX0V5GHsRvts/qClz+QcIHMSALV\n" + + "UIrumtxxdbL63pIw4ds0PeH5RtyR9JpS5pWxUk1MPUPoYSV9GPg2bPUEY99Ji8qi\n" + + "vA1kRTeBfAWC0OgBwbHu1zIKUukMd+pF/D/vKKovJ6I/sPiGXmUw2i4lYOUB0wWn\n" + + "QUyBLez1UMWKchyvpW0FYxMbv7j5zMcAH7d++vCWo3OEGfe4Uet6Q3/Dx83HAiEA\n" + + "mjtJp7XNrsgxbRDqETkHhv6zYH8Voo+gDgSO1m7XcH0CggEBAI5moswp++plZSBP\n" + + "Q9DdCNHt0AV13Toj1jf5M5DNmTX6P6/D/oRfi8Ui1fiCKFv+7lD0J2anCFUaLtu+\n" + + "j7v78gp5OChDp/n49K6DtKtZZRDmw/Bpm6LNdknmdN5kO5wVzbIXHTCCeNs/CJTF\n" + + "mSU5PvEaI4y3M5NraSgLPkq4gEv7/A8orGbKmj1Whj3F9t1Tosxdm/+WkPldMz2t\n" + + "gev+9RM2S6S9XoembRgwRaFVkpQmKoKpOoZcdqV47FLDq5BYH/5POeJ9wLuAHjxQ\n" + + "5CMKo4p/lW7BCd4kuGWFT+OFFXfG2v6EtlqFbXBiFWLxyMsOtkUqWARCqEHhyucl\n" + + "TSYlj60EIgIgLfA75+8KcKxdN8mr6gzGjQe7jPFGG42Ejhd7Q2F4wuw="); + + final String keyAlgo; + final String certStr; + final String privKeyStr; + + Cert(String keyAlgo, String certStr, String privKeyStr) { + this.keyAlgo = keyAlgo; + this.certStr = certStr; + this.privKeyStr = privKeyStr; + } + } } From 878c16f75f955f46f2cdc62bf0da413549dedace Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Tue, 19 May 2026 21:15:36 +0200 Subject: [PATCH 2/8] Backport 955d9fb554dbc0d12cea90eb85ffefafec9f34d1 8246330: Add TLS Tests for Legacy ECDSA curves --- .../net/ssl/templates/SSLSocketTemplate.java | 55 ++++++++ .../ssl/CipherSuite/DisabledCurve.java | 118 ++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 jdk/test/sun/security/ssl/CipherSuite/DisabledCurve.java diff --git a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java index 9f3c75632f4..49b4a72d539 100644 --- a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java +++ b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java @@ -357,12 +357,14 @@ private void doClientSide() throws Exception { // Trusted certificates. protected final static Cert[] TRUSTED_CERTS = { Cert.CA_ECDSA_SECP256R1, + Cert.CA_ECDSA_SECT283R1, Cert.CA_RSA_2048, Cert.CA_DSA_2048 }; // End entity certificate. protected final static Cert[] END_ENTITY_CERTS = { Cert.EE_ECDSA_SECP256R1, + Cert.EE_ECDSA_SECT283R1, Cert.EE_RSA_2048, Cert.EE_EC_RSA_SECP256R1, Cert.EE_DSA_2048 }; @@ -696,6 +698,32 @@ public static enum Cert { "p1YdWENftmDoNTJ3O6TNlXb90jKWgAirCXNBUompPtHKkO592eDyGcT1h8qjrKlm\n" + "Kw=="), + CA_ECDSA_SECT283R1( + "EC", + // SHA1withECDSA, curve sect283r1 + // Validity + // Not Before: May 26 06:06:52 2020 GMT + // Not After : May 21 06:06:52 2040 GMT + // Subject Key Identifier: + // CF:A3:99:ED:4C:6E:04:41:09:21:31:33:B6:80:D5:A7:BF:2B:98:04 + "-----BEGIN CERTIFICATE-----\n" + + "MIIB8TCCAY+gAwIBAgIJANQFsBngZ3iMMAsGByqGSM49BAEFADBdMQswCQYDVQQG\n" + + "EwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNBMQ8wDQYDVQQKEwZPcmFjbGUx\n" + + "DzANBgNVBAsTBkpQR1NRRTESMBAGA1UEAxMJc2VjdDI4M3IxMB4XDTIwMDUyNjE4\n" + + "MDY1MloXDTQwMDUyMTE4MDY1MlowXTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB\n" + + "MQswCQYDVQQHEwJTQTEPMA0GA1UEChMGT3JhY2xlMQ8wDQYDVQQLEwZKUEdTUUUx\n" + + "EjAQBgNVBAMTCXNlY3QyODNyMTBeMBAGByqGSM49AgEGBSuBBAARA0oABALatmDt\n" + + "QIhjpK4vJjv4GgC8CUH/VAWLUSQRU7yGGQ3NF8rVBARv0aehiII0nzjDVX5KrP/A\n" + + "w/DmW7q8PfEAIktuaA/tcKv/OKMyMDAwHQYDVR0OBBYEFM+jme1MbgRBCSExM7aA\n" + + "1ae/K5gEMA8GA1UdEwEB/wQFMAMBAf8wCwYHKoZIzj0EAQUAA08AMEwCJAGHsAP8\n" + + "HlcVqszra+fxq35juTxHJIfxTKIr7f54Ywtz7AJowgIkAxydv8g+dkuniOUAj0Xt\n" + + "FnGVp6HzKX5KM1zLpfqmix8ZPP/A\n" + + "-----END CERTIFICATE-----", + "MIGQAgEAMBAGByqGSM49AgEGBSuBBAARBHkwdwIBAQQkAdcyn/FxiNvuTsSgDehq\n" + + "SGFiTxAKNMMJfmsO6GHekzszFqjPoUwDSgAEAtq2YO1AiGOkri8mO/gaALwJQf9U\n" + + "BYtRJBFTvIYZDc0XytUEBG/Rp6GIgjSfOMNVfkqs/8DD8OZburw98QAiS25oD+1w\n" + + "q/84"), + CA_RSA_2048( "RSA", // SHA256withRSA, 2048 bits @@ -801,6 +829,33 @@ public static enum Cert { "tXHs6lmu6+uBmtJ5I9ZMJHEao4E4icdDcJ1F6+/FQFxYVRfefjt5X6ob3bRBrZIQ" + "xj4OzQQjAiEAsceWOM8do4etxp2zgnoNXV8PUUyqWhz1+0srcKV7FR4="), + EE_ECDSA_SECT283R1( + "EC", + // SHA1withECDSA, curve sect283r1 + // Validity + // Not Before: May 26 06:08:15 2020 GMT + // Not After : May 21 06:08:15 2040 GMT + // Authority Key Identifier: + // CF:A3:99:ED:4C:6E:04:41:09:21:31:33:B6:80:D5:A7:BF:2B:98:04 + "-----BEGIN CERTIFICATE-----\n" + + "MIICFTCCAbOgAwIBAgIJAM0Dd9zxR9CeMAsGByqGSM49BAEFADBdMQswCQYDVQQG\n" + + "EwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNBMQ8wDQYDVQQKEwZPcmFjbGUx\n" + + "DzANBgNVBAsTBkpQR1NRRTESMBAGA1UEAxMJc2VjdDI4M3IxMB4XDTIwMDUyNjE4\n" + + "MDgxNVoXDTQwMDUyMTE4MDgxNVowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB\n" + + "MQswCQYDVQQHEwJTQTEPMA0GA1UEChMGT3JhY2xlMQ8wDQYDVQQLEwZKUEdTUUUx\n" + + "FTATBgNVBAMMDHNlY3QyODNyMV9lZTBeMBAGByqGSM49AgEGBSuBBAARA0oABAMP\n" + + "oaMP2lIiCrNaFSePtZA8nBnqJXSGCz8kosKeYTqz/SPE1AN6BvM4xl0kPQZvJWMz\n" + + "fyTcm2Ar0PdbIh8f22vJfO+0JpfhnqNTMFEwHQYDVR0OBBYEFOzDGNWQhslU5ei4\n" + + "SYda/ro9DickMA8GA1UdEwQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUz6OZ7UxuBEEJ\n" + + "ITEztoDVp78rmAQwCwYHKoZIzj0EAQUAA08AMEwCJALYBWSYdbhRiW4mNulQh6/v\n" + + "dfHG3y/oMjzJEmT/A0WYl96ohgIkAbDC0Ke632RXtCZ4xa2FrmzP41Vb80mSH1iY\n" + + "FCJ3LVoTEUgN\n" + + "-----END CERTIFICATE-----", + "MIGQAgEAMBAGByqGSM49AgEGBSuBBAARBHkwdwIBAQQkAXq9LPYU+XSrImPzgO1e\n" + + "hsgjfTBXlWGveFUtn0OHPtbp7hzpoUwDSgAEAw+how/aUiIKs1oVJ4+1kDycGeol\n" + + "dIYLPySiwp5hOrP9I8TUA3oG8zjGXSQ9Bm8lYzN/JNybYCvQ91siHx/ba8l877Qm\n" + + "l+Ge"), + EE_ECDSA_SECP256R1( "EC", // SHA256withECDSA, curve secp256r1 diff --git a/jdk/test/sun/security/ssl/CipherSuite/DisabledCurve.java b/jdk/test/sun/security/ssl/CipherSuite/DisabledCurve.java new file mode 100644 index 00000000000..620b11b773e --- /dev/null +++ b/jdk/test/sun/security/ssl/CipherSuite/DisabledCurve.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8246330 + * @library /javax/net/ssl/templates + * @run main/othervm -Djdk.tls.namedGroups="sect283r1" + DisabledCurve DISABLE_NONE PASS + * @run main/othervm -Djdk.tls.namedGroups="sect283r1" + DisabledCurve sect283r1 FAIL +*/ +import java.security.Security; +import java.util.Arrays; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; + +public class DisabledCurve extends SSLSocketTemplate { + + private static volatile int index; + private static final String[][][] protocols = { + { { "TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1" }, { "TLSv1.2" } }, + { { "TLSv1.2" }, { "TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1" } }, + { { "TLSv1.2" }, { "TLSv1.2" } }, { { "TLSv1.1" }, { "TLSv1.1" } }, + { { "TLSv1" }, { "TLSv1" } } }; + + protected SSLContext createClientSSLContext() throws Exception { + return createSSLContext( + new SSLSocketTemplate.Cert[] { + SSLSocketTemplate.Cert.CA_ECDSA_SECT283R1 }, + new SSLSocketTemplate.Cert[] { + SSLSocketTemplate.Cert.EE_ECDSA_SECT283R1 }, + getClientContextParameters()); + } + + protected SSLContext createServerSSLContext() throws Exception { + return createSSLContext( + new SSLSocketTemplate.Cert[] { + SSLSocketTemplate.Cert.CA_ECDSA_SECT283R1 }, + new SSLSocketTemplate.Cert[] { + SSLSocketTemplate.Cert.EE_ECDSA_SECT283R1 }, + getServerContextParameters()); + } + + @Override + protected void configureClientSocket(SSLSocket socket) { + String[] ps = protocols[index][0]; + + System.out.print("Setting client protocol(s): "); + Arrays.stream(ps).forEachOrdered(System.out::print); + System.out.println(); + + socket.setEnabledProtocols(ps); + } + + @Override + protected void configureServerSocket(SSLServerSocket serverSocket) { + String[] ps = protocols[index][1]; + + System.out.print("Setting server protocol(s): "); + Arrays.stream(ps).forEachOrdered(System.out::print); + System.out.println(); + + serverSocket.setEnabledProtocols(ps); + } + + public static void main(String[] args) throws Exception { + String expected = args[1]; + String disabledName = ("DISABLE_NONE".equals(args[0]) ? "" : args[0]); + if (disabledName.equals("")) { + Security.setProperty("jdk.disabled.namedCurves", ""); + } + System.setProperty("jdk.sunec.disableNative", "false"); + + for (index = 0; index < protocols.length; index++) { + try { + (new DisabledCurve()).run(); + if (expected.equals("FAIL")) { + throw new RuntimeException( + "The test case should not reach here"); + } + } catch (SSLException | IllegalStateException ssle) { + if ((expected.equals("FAIL")) + && Security.getProperty("jdk.disabled.namedCurves") + .contains(disabledName)) { + System.out.println( + "Expected exception was thrown: TEST PASSED"); + } else { + throw new RuntimeException(ssle); + } + + } + + } + } +} From 05f6511034ad18e49e1335b96a7bf3ecf8b5d1d4 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 20 May 2026 14:22:09 +0200 Subject: [PATCH 3/8] Re-enable TLS versions in the test --- jdk/test/sun/security/ssl/CipherSuite/DisabledCurve.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jdk/test/sun/security/ssl/CipherSuite/DisabledCurve.java b/jdk/test/sun/security/ssl/CipherSuite/DisabledCurve.java index 620b11b773e..edddf3dada0 100644 --- a/jdk/test/sun/security/ssl/CipherSuite/DisabledCurve.java +++ b/jdk/test/sun/security/ssl/CipherSuite/DisabledCurve.java @@ -25,6 +25,7 @@ * @test * @bug 8246330 * @library /javax/net/ssl/templates + * /lib/security * @run main/othervm -Djdk.tls.namedGroups="sect283r1" DisabledCurve DISABLE_NONE PASS * @run main/othervm -Djdk.tls.namedGroups="sect283r1" @@ -94,6 +95,9 @@ public static void main(String[] args) throws Exception { } System.setProperty("jdk.sunec.disableNative", "false"); + // Re-enable TLSv1 and TLSv1.1 since test depends on it. + SecurityUtils.removeFromDisabledTlsAlgs("TLSv1", "TLSv1.1"); + for (index = 0; index < protocols.length; index++) { try { (new DisabledCurve()).run(); From 0dc5b58f02b8e2b37a1f2ef5201fd7900319c2c5 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Fri, 22 May 2026 17:13:53 +0200 Subject: [PATCH 4/8] Backport 3aa7dcd2671ab596d1205ea2c78352eae2ce608a 8259662: Don't wrap SocketExceptions into SSLExceptions in SSLSocketImpl --- .../sun/security/ssl/SSLSocketImpl.java | 28 +++- .../sun/security/ssl/SSLTransport.java | 6 +- .../ssl/SSLSession/TestEnabledProtocols.java | 5 +- .../ssl/SSLContextImpl/TrustTrustedCert.java | 6 +- .../SSLSocketShouldThrowSocketException.java | 153 ++++++++++++++++++ ...va => SocketExceptionForSocketIssues.java} | 11 +- 6 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketShouldThrowSocketException.java rename jdk/test/sun/security/ssl/SSLSocketImpl/{SSLExceptionForIOIssue.java => SocketExceptionForSocketIssues.java} (94%) diff --git a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java index fe0b6be479c..19b37eb7434 100644 --- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -73,6 +73,16 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl implements SSLTransport { + /** + * ERROR HANDLING GUIDELINES + * (which exceptions to throw and catch and which not to throw and catch) + * + * - if there is an IOException (SocketException) when accessing the + * underlying Socket, pass it through + * + * - do not throw IOExceptions, throw SSLExceptions (or a subclass) + */ + final SSLContextImpl sslContext; final TransportContext conContext; @@ -439,6 +449,8 @@ public void startHandshake() throws IOException { if (!conContext.isNegotiated) { readHandshakeRecord(); } + } catch (SocketException se) { + handleException(se); } catch (IOException ioe) { throw conContext.fatal(Alert.HANDSHAKE_FAILURE, "Couldn't kickstart handshaking", ioe); @@ -1311,7 +1323,8 @@ private int readHandshakeRecord() throws IOException { conContext.isNegotiated) { return 0; } - } catch (SSLException ssle) { + } catch (SSLException | SocketException ssle) { + // don't change exception in case of SocketException throw ssle; } catch (IOException ioe) { if (!(ioe instanceof SSLException)) { @@ -1377,7 +1390,8 @@ private ByteBuffer readApplicationRecord( buffer.position() > 0) { return buffer; } - } catch (SSLException ssle) { + } catch (SSLException | SocketException ssle) { + // don't change exception in case of SocketException. throw ssle; } catch (IOException ioe) { if (!(ioe instanceof SSLException)) { @@ -1569,6 +1583,16 @@ private void handleException(Exception cause) throws IOException { } } + if (cause instanceof SocketException) { + try { + conContext.fatal(alert, cause); + } catch (Exception e) { + // Just delivering the fatal alert, re-throw the socket exception instead. + } + + throw (SocketException)cause; + } + throw conContext.fatal(alert, cause); } diff --git a/jdk/src/share/classes/sun/security/ssl/SSLTransport.java b/jdk/src/share/classes/sun/security/ssl/SSLTransport.java index b3d03b37044..18aa2e62860 100644 --- a/jdk/src/share/classes/sun/security/ssl/SSLTransport.java +++ b/jdk/src/share/classes/sun/security/ssl/SSLTransport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.io.EOFException; import java.io.IOException; import java.nio.ByteBuffer; +import java.net.SocketException; import javax.crypto.AEADBadTagException; import javax.crypto.BadPaddingException; import javax.net.ssl.SSLHandshakeException; @@ -134,6 +135,9 @@ static Plaintext decode(TransportContext context, } catch (EOFException eofe) { // rethrow EOFException, the call will handle it if neede. throw eofe; + } catch (SocketException se) { + // don't close the Socket in case of SocketException. + throw se; } catch (IOException ioe) { throw context.fatal(Alert.UNEXPECTED_MESSAGE, ioe); } diff --git a/jdk/test/javax/net/ssl/SSLSession/TestEnabledProtocols.java b/jdk/test/javax/net/ssl/SSLSession/TestEnabledProtocols.java index cd8ad678b47..355a290355c 100644 --- a/jdk/test/javax/net/ssl/SSLSession/TestEnabledProtocols.java +++ b/jdk/test/javax/net/ssl/SSLSession/TestEnabledProtocols.java @@ -41,6 +41,7 @@ import java.io.InputStream; import java.io.InterruptedIOException; import java.io.OutputStream; +import java.net.SocketException; import java.security.Security; import java.util.Arrays; @@ -86,10 +87,10 @@ protected void runServerApplication(SSLSocket socket) throws Exception { se.printStackTrace(System.out); } catch (InterruptedIOException ioe) { // must have been interrupted, no harm - } catch (SSLException ssle) { + } catch (SSLException | SocketException se) { // The client side may have closed the socket. System.out.println("Server SSLException:"); - ssle.printStackTrace(System.out); + se.printStackTrace(System.out); } catch (Exception e) { System.out.println("Server exception:"); e.printStackTrace(System.out); diff --git a/jdk/test/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java b/jdk/test/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java index 51fdafff7da..6d705000e86 100644 --- a/jdk/test/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java +++ b/jdk/test/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,9 +131,9 @@ protected void runServerApplication(SSLSocket socket) throws Exception { sslIS.read(); sslOS.write('A'); sslOS.flush(); - } catch (SSLException ssle) { + } catch (SSLException | SocketException se) { if (!expectFail) { - throw ssle; + throw se; } // Otherwise, ignore. } } diff --git a/jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketShouldThrowSocketException.java b/jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketShouldThrowSocketException.java new file mode 100644 index 00000000000..46cedd8f15e --- /dev/null +++ b/jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketShouldThrowSocketException.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021, Amazon and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8214339 8259662 + * @summary When a SocketException is thrown by the underlying layer, It + * should be thrown as is and not be transformed to an SSLException. + * @library /javax/net/ssl/templates + * @run main/othervm SSLSocketShouldThrowSocketException + */ + +import java.io.*; +import java.net.*; +import java.util.*; +import java.security.*; +import javax.net.ssl.*; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class SSLSocketShouldThrowSocketException extends SSLSocketTemplate { + + boolean handshake; + + private final CountDownLatch clientTerminatedCondition = new CountDownLatch(1); + + SSLSocketShouldThrowSocketException(boolean handshake) { + this.handshake = handshake; + } + + @Override + protected boolean isCustomizedClientConnection() { + return true; + } + + @Override + protected void runServerApplication(SSLSocket socket) throws Exception { + clientTerminatedCondition.await(30L, TimeUnit.SECONDS); + } + + @Override + protected void runClientApplication(int serverPort) throws Exception { + Socket baseSocket = new Socket("localhost", serverPort); + + SSLSocketFactory sslsf = + (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) + sslsf.createSocket(baseSocket, "localhost", serverPort, false); + + if (this.handshake) { + testHandshakeClose(baseSocket, sslSocket); + } else { + testDataClose(baseSocket, sslSocket); + } + + clientTerminatedCondition.countDown(); + + } + + private void testHandshakeClose(Socket baseSocket, SSLSocket sslSocket) throws Exception { + Thread aborter = new Thread() { + @Override + public void run() { + + try { + Thread.sleep(10); + System.err.println("Closing the client socket : " + System.nanoTime()); + baseSocket.close(); + } catch (Exception ieo) { + ieo.printStackTrace(); + } + } + }; + + aborter.start(); + + try { + // handshaking + System.err.println("Client starting handshake: " + System.nanoTime()); + sslSocket.startHandshake(); + throw new Exception("Start handshake did not throw an exception"); + } catch (SocketException se) { + System.err.println("Caught Expected SocketException"); + } + + aborter.join(); + } + + private void testDataClose(Socket baseSocket, SSLSocket sslSocket) throws Exception{ + + CountDownLatch handshakeCondition = new CountDownLatch(1); + + Thread aborter = new Thread() { + @Override + public void run() { + + try { + handshakeCondition.await(10L, TimeUnit.SECONDS); + System.err.println("Closing the client socket : " + System.nanoTime()); + baseSocket.close(); + } catch (Exception ieo) { + ieo.printStackTrace(); + } + } + }; + + aborter.start(); + + try { + // handshaking + System.err.println("Client starting handshake: " + System.nanoTime()); + sslSocket.startHandshake(); + handshakeCondition.countDown(); + System.err.println("Reading data from server"); + BufferedReader is = new BufferedReader( + new InputStreamReader(sslSocket.getInputStream())); + String data = is.readLine(); + throw new Exception("Start handshake did not throw an exception"); + } catch (SocketException se) { + System.err.println("Caught Expected SocketException"); + } + + aborter.join(); + } + + public static void main(String[] args) throws Exception { + // SocketException should be throws during a handshake phase. + (new SSLSocketShouldThrowSocketException(true)).run(); + // SocketException should be throw during the application data phase. + (new SSLSocketShouldThrowSocketException(false)).run(); + } +} diff --git a/jdk/test/sun/security/ssl/SSLSocketImpl/SSLExceptionForIOIssue.java b/jdk/test/sun/security/ssl/SSLSocketImpl/SocketExceptionForSocketIssues.java similarity index 94% rename from jdk/test/sun/security/ssl/SSLSocketImpl/SSLExceptionForIOIssue.java rename to jdk/test/sun/security/ssl/SSLSocketImpl/SocketExceptionForSocketIssues.java index 3e626a2577c..58a0c2ca38a 100644 --- a/jdk/test/sun/security/ssl/SSLSocketImpl/SSLExceptionForIOIssue.java +++ b/jdk/test/sun/security/ssl/SSLSocketImpl/SocketExceptionForSocketIssues.java @@ -31,18 +31,19 @@ * @bug 8214339 * @summary SSLSocketImpl erroneously wraps SocketException * @library /javax/net/ssl/templates - * @run main/othervm SSLExceptionForIOIssue + * @run main/othervm SocketExceptionForSocketIssues */ import javax.net.ssl.*; import java.io.*; import java.net.InetAddress; +import java.net.SocketException; -public class SSLExceptionForIOIssue implements SSLContextTemplate { +public class SocketExceptionForSocketIssues implements SSLContextTemplate { public static void main(String[] args) throws Exception { System.err.println("==================================="); - new SSLExceptionForIOIssue().test(); + new SocketExceptionForSocketIssues().test(); } private void test() throws Exception { @@ -79,9 +80,9 @@ private void test() throws Exception { os.flush(); } catch (SSLProtocolException | SSLHandshakeException sslhe) { throw sslhe; - } catch (SSLException ssle) { + } catch (SocketException se) { // the expected exception, ignore it - System.err.println("server exception: " + ssle); + System.err.println("server exception: " + se); } finally { if (listenSocket != null) { listenSocket.close(); From b09f14af32440c32bfc62313e6bed589d2332270 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 27 May 2026 14:27:44 +0200 Subject: [PATCH 5/8] Backport 6414dec64a01d94edb57c5380850ef536cd3bcec 8250839: Improve test template SSLEngineTemplate with SSLContextTemplate --- .../net/ssl/templates/SSLEngineTemplate.java | 411 ++++++------------ 1 file changed, 121 insertions(+), 290 deletions(-) diff --git a/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java b/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java index 32470d11e9e..24ff8e08448 100644 --- a/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java +++ b/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,10 +26,15 @@ /* * @test - * @bug 1234567 - * @summary SSLEngine has not yet caused Solaris kernel to panic + * @bug 8250839 + * @summary Improve test template SSLEngineTemplate with SSLContextTemplate + * @build SSLContextTemplate * @run main/othervm SSLEngineTemplate */ +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import java.nio.ByteBuffer; + /** * A SSLEngine usage example which simplifies the presentation * by removing the I/O and multi-threading concerns. @@ -44,231 +49,139 @@ * * When this application runs, notice that several messages * (wrap/unwrap) pass before any application data is consumed or - * produced. (For more information, please see the SSL/TLS - * specifications.) There may several steps for a successful handshake, - * so it's typical to see the following series of operations: - * - * client server message - * ====== ====== ======= - * wrap() ... ClientHello - * ... unwrap() ClientHello - * ... wrap() ServerHello/Certificate - * unwrap() ... ServerHello/Certificate - * wrap() ... ClientKeyExchange - * wrap() ... ChangeCipherSpec - * wrap() ... Finished - * ... unwrap() ClientKeyExchange - * ... unwrap() ChangeCipherSpec - * ... unwrap() Finished - * ... wrap() ChangeCipherSpec - * ... wrap() Finished - * unwrap() ... ChangeCipherSpec - * unwrap() ... Finished + * produced. */ -import javax.net.ssl.*; -import javax.net.ssl.SSLEngineResult.*; -import java.io.*; -import java.security.*; -import java.nio.*; - -public class SSLEngineTemplate { - - /* - * Enables logging of the SSLEngine operations. - */ - private static final boolean logging = true; - - /* - * Enables the JSSE system debugging system property: - * - * -Djavax.net.debug=all - * - * This gives a lot of low-level information about operations underway, - * including specific handshake messages, and might be best examined - * after gaining some familiarity with this application. - */ - private static final boolean debug = false; +public class SSLEngineTemplate implements SSLContextTemplate { + private final SSLEngine clientEngine; // client Engine + private final ByteBuffer clientOut; // write side of clientEngine + private final ByteBuffer clientIn; // read side of clientEngine + + private final SSLEngine serverEngine; // server Engine + private final ByteBuffer serverOut; // write side of serverEngine + private final ByteBuffer serverIn; // read side of serverEngine + + // For data transport, this example uses local ByteBuffers. This + // isn't really useful, but the purpose of this example is to show + // SSLEngine concepts, not how to do network transport. + private final ByteBuffer cTOs; // "reliable" transport client->server + private final ByteBuffer sTOc; // "reliable" transport server->client + + private SSLEngineTemplate() throws Exception { + serverEngine = configureServerEngine( + createServerSSLContext().createSSLEngine()); + + clientEngine = configureClientEngine( + createClientSSLContext().createSSLEngine()); + + // We'll assume the buffer sizes are the same + // between client and server. + SSLSession session = clientEngine.getSession(); + int appBufferMax = session.getApplicationBufferSize(); + int netBufferMax = session.getPacketBufferSize(); - private final SSLContext sslc; + // We'll make the input buffers a bit bigger than the max needed + // size, so that unwrap()s following a successful data transfer + // won't generate BUFFER_OVERFLOWS. + // + // We'll use a mix of direct and indirect ByteBuffers for + // tutorial purposes only. In reality, only use direct + // ByteBuffers when they give a clear performance enhancement. + clientIn = ByteBuffer.allocate(appBufferMax + 50); + serverIn = ByteBuffer.allocate(appBufferMax + 50); - private SSLEngine clientEngine; // client Engine - private ByteBuffer clientOut; // write side of clientEngine - private ByteBuffer clientIn; // read side of clientEngine + cTOs = ByteBuffer.allocateDirect(netBufferMax); + sTOc = ByteBuffer.allocateDirect(netBufferMax); - private SSLEngine serverEngine; // server Engine - private ByteBuffer serverOut; // write side of serverEngine - private ByteBuffer serverIn; // read side of serverEngine + clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes()); + serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes()); + } - /* - * For data transport, this example uses local ByteBuffers. This - * isn't really useful, but the purpose of this example is to show - * SSLEngine concepts, not how to do network transport. - */ - private ByteBuffer cTOs; // "reliable" transport client->server - private ByteBuffer sTOc; // "reliable" transport server->client + // + // Protected methods could be used to customize the test case. + // /* - * The following is to set up the keystores. + * Configure the client side engine. */ - private static final String pathToStores = "../etc"; - private static final String keyStoreFile = "keystore"; - private static final String trustStoreFile = "truststore"; - private static final char[] passphrase = "passphrase".toCharArray(); - - private static final String keyFilename = - System.getProperty("test.src", ".") + "/" + pathToStores + - "/" + keyStoreFile; - private static final String trustFilename = - System.getProperty("test.src", ".") + "/" + pathToStores + - "/" + trustStoreFile; - - /* - * Main entry point for this test. - */ - public static void main(String args[]) throws Exception { - if (debug) { - System.setProperty("javax.net.debug", "all"); - } + protected SSLEngine configureClientEngine(SSLEngine clientEngine) { + clientEngine.setUseClientMode(true); - SSLEngineTemplate test = new SSLEngineTemplate(); - test.runTest(); + // Get/set parameters if needed + // SSLParameters paramsClient = clientEngine.getSSLParameters(); + // clientEngine.setSSLParameters(paramsClient); - System.out.println("Test Passed."); + return clientEngine; } /* - * Create an initialized SSLContext to use for these tests. + * Configure the server side engine. */ - public SSLEngineTemplate() throws Exception { - - KeyStore ks = KeyStore.getInstance("JKS"); - KeyStore ts = KeyStore.getInstance("JKS"); - - ks.load(new FileInputStream(keyFilename), passphrase); - ts.load(new FileInputStream(trustFilename), passphrase); - - KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - kmf.init(ks, passphrase); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); - tmf.init(ts); - - SSLContext sslCtx = SSLContext.getInstance("TLS"); + protected SSLEngine configureServerEngine(SSLEngine serverEngine) { + serverEngine.setUseClientMode(false); + serverEngine.setNeedClientAuth(true); - sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + // Get/set parameters if needed + // + // SSLParameters paramsServer = serverEngine.getSSLParameters(); + // serverEngine.setSSLParameters(paramsServer); - sslc = sslCtx; + return serverEngine; } - /* - * Run the test. - * - * Sit in a tight loop, both engines calling wrap/unwrap regardless - * of whether data is available or not. We do this until both engines - * report back they are closed. - * - * The main loop handles all of the I/O phases of the SSLEngine's - * lifetime: - * - * initial handshaking - * application data transfer - * engine closing - * - * One could easily separate these phases into separate - * sections of code. - */ - private void runTest() throws Exception { - boolean dataDone = false; + public static void main(String[] args) throws Exception { + new SSLEngineTemplate().runTest(); + } - createSSLEngines(); - createBuffers(); + // + // Private methods that used to build the common part of the test. + // - // results from client's last operation + private void runTest() throws Exception { SSLEngineResult clientResult; - - // results from server's last operation SSLEngineResult serverResult; - /* - * Examining the SSLEngineResults could be much more involved, - * and may alter the overall flow of the application. - * - * For example, if we received a BUFFER_OVERFLOW when trying - * to write to the output pipe, we could reallocate a larger - * pipe, but instead we wait for the peer to drain it. - */ - Exception clientException = null; - Exception serverException = null; - - while (!isEngineClosed(clientEngine) - || !isEngineClosed(serverEngine)) { - - log("================"); - - try { - clientResult = clientEngine.wrap(clientOut, cTOs); - log("client wrap: ", clientResult); - } catch (Exception e) { - clientException = e; - System.out.println("Client wrap() threw: " + e.getMessage()); - } - logEngineStatus(clientEngine); - runDelegatedTasks(clientEngine); + boolean dataDone = false; + while (isOpen(clientEngine) || isOpen(serverEngine)) { + log("================="); - log("----"); + // client wrap + log("---Client Wrap---"); + clientResult = clientEngine.wrap(clientOut, cTOs); + logEngineStatus(clientEngine, clientResult); + runDelegatedTasks(clientEngine); - try { - serverResult = serverEngine.wrap(serverOut, sTOc); - log("server wrap: ", serverResult); - } catch (Exception e) { - serverException = e; - System.out.println("Server wrap() threw: " + e.getMessage()); - } - logEngineStatus(serverEngine); + // server wrap + log("---Server Wrap---"); + serverResult = serverEngine.wrap(serverOut, sTOc); + logEngineStatus(serverEngine, serverResult); runDelegatedTasks(serverEngine); cTOs.flip(); sTOc.flip(); - log("--------"); - - try { - clientResult = clientEngine.unwrap(sTOc, clientIn); - log("client unwrap: ", clientResult); - } catch (Exception e) { - clientException = e; - System.out.println("Client unwrap() threw: " + e.getMessage()); - } - logEngineStatus(clientEngine); + // client unwrap + log("---Client Unwrap---"); + clientResult = clientEngine.unwrap(sTOc, clientIn); + logEngineStatus(clientEngine, clientResult); runDelegatedTasks(clientEngine); - log("----"); - - try { - serverResult = serverEngine.unwrap(cTOs, serverIn); - log("server unwrap: ", serverResult); - } catch (Exception e) { - serverException = e; - System.out.println("Server unwrap() threw: " + e.getMessage()); - } - logEngineStatus(serverEngine); + // server unwrap + log("---Server Unwrap---"); + serverResult = serverEngine.unwrap(cTOs, serverIn); + logEngineStatus(serverEngine, serverResult); runDelegatedTasks(serverEngine); cTOs.compact(); sTOc.compact(); - /* - * After we've transfered all application data between the client - * and server, we close the clientEngine's outbound stream. - * This generates a close_notify handshake message, which the - * server engine receives and responds by closing itself. - */ + // After we've transferred all application data between the client + // and server, we close the clientEngine's outbound stream. + // This generates a close_notify handshake message, which the + // server engine receives and responds by closing itself. if (!dataDone && (clientOut.limit() == serverIn.position()) && (serverOut.limit() == clientIn.position())) { - /* - * A sanity check to ensure we got what was sent. - */ + // A sanity check to ensure we got what was sent. checkTransfer(serverOut, clientIn); checkTransfer(clientOut, serverIn); @@ -284,78 +197,33 @@ private void runTest() throws Exception { } } + private static boolean isOpen(SSLEngine engine) { + return (!engine.isOutboundDone() || !engine.isInboundDone()); + } + private static void logEngineStatus(SSLEngine engine) { - log("\tCurrent HS State " + engine.getHandshakeStatus().toString()); - log("\tisInboundDone(): " + engine.isInboundDone()); + log("\tCurrent HS State: " + engine.getHandshakeStatus()); + log("\tisInboundDone() : " + engine.isInboundDone()); log("\tisOutboundDone(): " + engine.isOutboundDone()); } - /* - * Using the SSLContext created during object creation, - * create/configure the SSLEngines we'll use for this test. - */ - private void createSSLEngines() throws Exception { - /* - * Configure the serverEngine to act as a server in the SSL/TLS - * handshake. Also, require SSL client authentication. - */ - serverEngine = sslc.createSSLEngine(); - serverEngine.setUseClientMode(false); - serverEngine.setNeedClientAuth(true); - - // Get/set parameters if needed - SSLParameters paramsServer = serverEngine.getSSLParameters(); - serverEngine.setSSLParameters(paramsServer); - - /* - * Similar to above, but using client mode instead. - */ - clientEngine = sslc.createSSLEngine("client", 80); - clientEngine.setUseClientMode(true); - - // Get/set parameters if needed - SSLParameters paramsClient = clientEngine.getSSLParameters(); - clientEngine.setSSLParameters(paramsClient); + private static void logEngineStatus( + SSLEngine engine, SSLEngineResult result) { + log("\tResult Status : " + result.getStatus()); + log("\tResult HS Status : " + result.getHandshakeStatus()); + log("\tEngine HS Status : " + engine.getHandshakeStatus()); + log("\tisInboundDone() : " + engine.isInboundDone()); + log("\tisOutboundDone() : " + engine.isOutboundDone()); + log("\tMore Result : " + result); } - /* - * Create and size the buffers appropriately. - */ - private void createBuffers() { - - /* - * We'll assume the buffer sizes are the same - * between client and server. - */ - SSLSession session = clientEngine.getSession(); - int appBufferMax = session.getApplicationBufferSize(); - int netBufferMax = session.getPacketBufferSize(); - - /* - * We'll make the input buffers a bit bigger than the max needed - * size, so that unwrap()s following a successful data transfer - * won't generate BUFFER_OVERFLOWS. - * - * We'll use a mix of direct and indirect ByteBuffers for - * tutorial purposes only. In reality, only use direct - * ByteBuffers when they give a clear performance enhancement. - */ - clientIn = ByteBuffer.allocate(appBufferMax + 50); - serverIn = ByteBuffer.allocate(appBufferMax + 50); - - cTOs = ByteBuffer.allocateDirect(netBufferMax); - sTOc = ByteBuffer.allocateDirect(netBufferMax); - - clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes()); - serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes()); + private static void log(String message) { + System.err.println(message); } - /* - * If the result indicates that we have outstanding tasks to do, - * go ahead and run them in this thread. - */ + // If the result indicates that we have outstanding tasks to do, + // go ahead and run them in this thread. private static void runDelegatedTasks(SSLEngine engine) throws Exception { - if (engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable; while ((runnable = engine.getDelegatedTask()) != null) { @@ -365,19 +233,13 @@ private static void runDelegatedTasks(SSLEngine engine) throws Exception { HandshakeStatus hsStatus = engine.getHandshakeStatus(); if (hsStatus == HandshakeStatus.NEED_TASK) { throw new Exception( - "handshake shouldn't need additional tasks"); + "handshake shouldn't need additional tasks"); } logEngineStatus(engine); } } - private static boolean isEngineClosed(SSLEngine engine) { - return (engine.isOutboundDone() && engine.isInboundDone()); - } - - /* - * Simple check to make sure everything came across as expected. - */ + // Simple check to make sure everything came across as expected. private static void checkTransfer(ByteBuffer a, ByteBuffer b) throws Exception { a.flip(); @@ -394,35 +256,4 @@ private static void checkTransfer(ByteBuffer a, ByteBuffer b) a.limit(a.capacity()); b.limit(b.capacity()); } - - /* - * Logging code - */ - private static boolean resultOnce = true; - - private static void log(String str, SSLEngineResult result) { - if (!logging) { - return; - } - if (resultOnce) { - resultOnce = false; - System.out.println("The format of the SSLEngineResult is: \n" + - "\t\"getStatus() / getHandshakeStatus()\" +\n" + - "\t\"bytesConsumed() / bytesProduced()\"\n"); - } - HandshakeStatus hsStatus = result.getHandshakeStatus(); - log(str + - result.getStatus() + "/" + hsStatus + ", " + - result.bytesConsumed() + "/" + result.bytesProduced() + - " bytes"); - if (hsStatus == HandshakeStatus.FINISHED) { - log("\t...ready for application data"); - } - } - - private static void log(String str) { - if (logging) { - System.out.println(str); - } - } } From 37e03efc87d6c7b7cea3d80604e057951396a4de Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 27 May 2026 18:33:34 +0200 Subject: [PATCH 6/8] Backport 15c9397e45f094718fb976da9104364b83569c05 8326643: JDK server does not send a dummy change_cipher_spec record after HelloRetryRequest message --- .../classes/sun/security/ssl/ServerHello.java | 11 +- .../net/ssl/TLSv13/EngineOutOfSeqCCS.java | 277 ++++++++++++++++++ .../net/ssl/templates/SSLEngineTemplate.java | 20 +- 3 files changed, 297 insertions(+), 11 deletions(-) create mode 100644 jdk/test/javax/net/ssl/TLSv13/EngineOutOfSeqCCS.java diff --git a/jdk/src/share/classes/sun/security/ssl/ServerHello.java b/jdk/src/share/classes/sun/security/ssl/ServerHello.java index ebf80d9fc68..9e888eb964d 100644 --- a/jdk/src/share/classes/sun/security/ssl/ServerHello.java +++ b/jdk/src/share/classes/sun/security/ssl/ServerHello.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -779,6 +779,15 @@ public byte[] produce(ConnectionContext context, hhrm.write(shc.handshakeOutput); shc.handshakeOutput.flush(); + // In TLS1.3 middlebox compatibility mode the server sends a + // dummy change_cipher_spec record immediately after its + // first handshake message. This may either be after + // a ServerHello or a HelloRetryRequest. + // (RFC 8446, Appendix D.4) + shc.conContext.outputRecord.changeWriteCiphers( + SSLWriteCipher.nullTlsWriteCipher(), + (clientHello.sessionId.length() != 0)); + // Stateless, shall we clean up the handshake context as well? shc.handshakeHash.finish(); // forgot about the handshake hash shc.handshakeExtensions.clear(); diff --git a/jdk/test/javax/net/ssl/TLSv13/EngineOutOfSeqCCS.java b/jdk/test/javax/net/ssl/TLSv13/EngineOutOfSeqCCS.java new file mode 100644 index 00000000000..94a2c0fe311 --- /dev/null +++ b/jdk/test/javax/net/ssl/TLSv13/EngineOutOfSeqCCS.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8326643 + * @summary Test for out-of-sequence change_cipher_spec in TLSv1.3 + * @library /javax/net/ssl/templates + * @run main/othervm EngineOutOfSeqCCS + */ + +import java.nio.ByteBuffer; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLParameters; + +public class EngineOutOfSeqCCS extends SSLEngineTemplate { + + /* + * Enables logging of the SSLEngine operations. + */ + private static final boolean logging = true; + private static final boolean dumpBufs = true; + + // Define a few basic TLS records we might need + private static final int TLS_RECTYPE_CCS = 0x14; + private static final int TLS_RECTYPE_ALERT = 0x15; + private static final int TLS_RECTYPE_HANDSHAKE = 0x16; + private static final int TLS_RECTYPE_APPDATA = 0x17; + + SSLEngineResult clientResult, serverResult; + + public EngineOutOfSeqCCS() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception{ + new EngineOutOfSeqCCS().runDemo(); + } + + private void runDemo() throws Exception { + + // Client generates Client Hello + clientResult = clientEngine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + runDelegatedTasks(clientEngine); + cTOs.flip(); + dumpByteBuffer("CLIENT-TO-SERVER", cTOs); + + // Server consumes Client Hello + serverResult = serverEngine.unwrap(cTOs, serverIn); + log("server unwrap: ", serverResult); + runDelegatedTasks(serverEngine); + cTOs.compact(); + + // Server generates ServerHello/HelloRetryRequest + serverResult = serverEngine.wrap(serverOut, sTOc); + log("server wrap: ", serverResult); + runDelegatedTasks(serverEngine); + sTOc.flip(); + + dumpByteBuffer("SERVER-TO-CLIENT", sTOc); + + // client consumes ServerHello/HelloRetryRequest + clientResult = clientEngine.unwrap(sTOc, clientIn); + log("client unwrap: ", clientResult); + runDelegatedTasks(clientEngine); + sTOc.compact(); + + // Server generates CCS + serverResult = serverEngine.wrap(serverOut, sTOc); + log("server wrap: ", serverResult); + runDelegatedTasks(serverEngine); + sTOc.flip(); + dumpByteBuffer("SERVER-TO-CLIENT", sTOc); + + if (isTlsMessage(sTOc, TLS_RECTYPE_CCS)) { + System.out.println("=========== CCS found ==========="); + } else { + // In TLS1.3 middlebox compatibility mode the server sends a + // dummy change_cipher_spec record immediately after its + // first handshake message. This may either be after + // a ServerHello or a HelloRetryRequest. + // (RFC 8446, Appendix D.4) + throw new SSLException( + "Server should generate change_cipher_spec record"); + } + clientEngine.closeOutbound(); + serverEngine.closeOutbound(); + } + + /** + * Look at an incoming TLS record and see if it is the desired + * record type, and where appropriate the correct subtype. + * + * @param srcRecord The input TLS record to be evaluated. This + * method will only look at the leading message if multiple + * TLS handshake messages are coalesced into a single record. + * @param reqRecType The requested TLS record type + * @param recParams Zero or more integer sub type fields. For CCS + * and ApplicationData, no params are used. For handshake records, + * one value corresponding to the HandshakeType is required. + * For Alerts, two values corresponding to AlertLevel and + * AlertDescription are necessary. + * + * @return true if the proper handshake message is the first one + * in the input record, false otherwise. + */ + private boolean isTlsMessage(ByteBuffer srcRecord, int reqRecType, + int... recParams) { + boolean foundMsg = false; + + if (srcRecord.hasRemaining()) { + srcRecord.mark(); + + // Grab the fields from the TLS Record + int recordType = Byte.toUnsignedInt(srcRecord.get()); + byte ver_major = srcRecord.get(); + byte ver_minor = srcRecord.get(); + + if (recordType == reqRecType) { + // For any zero-length recParams, making sure the requested + // type is sufficient. + if (recParams.length == 0) { + foundMsg = true; + } else { + switch (recordType) { + case TLS_RECTYPE_CCS: + case TLS_RECTYPE_APPDATA: + // We really shouldn't find ourselves here, but + // if someone asked for these types and had more + // recParams we can ignore them. + foundMsg = true; + break; + case TLS_RECTYPE_ALERT: + // Needs two params, AlertLevel and + //AlertDescription + if (recParams.length != 2) { + throw new RuntimeException( + "Test for Alert requires level and desc."); + } else { + int level = Byte.toUnsignedInt( + srcRecord.get()); + int desc = Byte.toUnsignedInt(srcRecord.get()); + if (level == recParams[0] && + desc == recParams[1]) { + foundMsg = true; + } + } + break; + case TLS_RECTYPE_HANDSHAKE: + // Needs one parameter, HandshakeType + if (recParams.length != 1) { + throw new RuntimeException( + "Test for Handshake requires only HS type"); + } else { + // Go into the first handshake message in the + // record and grab the handshake message header. + // All we need to do is parse out the leading + // byte. + int msgHdr = srcRecord.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + if (msgType == recParams[0]) { + foundMsg = true; + } + } + break; + } + } + } + + srcRecord.reset(); + } + + return foundMsg; + } + + private static String tlsRecType(int type) { + switch (type) { + case 20: + return "Change Cipher Spec"; + case 21: + return "Alert"; + case 22: + return "Handshake"; + case 23: + return "Application Data"; + default: + return ("Unknown (" + type + ")"); + } + } + + /* + * Logging code + */ + private static boolean resultOnce = true; + + private static void log(String str, SSLEngineResult result) { + if (!logging) { + return; + } + if (resultOnce) { + resultOnce = false; + System.out.println("The format of the SSLEngineResult is: \n" + + "\t\"getStatus() / getHandshakeStatus()\" +\n" + + "\t\"bytesConsumed() / bytesProduced()\"\n"); + } + HandshakeStatus hsStatus = result.getHandshakeStatus(); + log(str + + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + log("\t...ready for application data"); + } + } + + private static void log(String str) { + if (logging) { + System.out.println(str); + } + } + + /** + * Hex-dumps a ByteBuffer to stdout. + */ + private static void dumpByteBuffer(String header, ByteBuffer bBuf) { + if (!dumpBufs) { + return; + } + + int bufLen = bBuf.remaining(); + if (bufLen > 0) { + bBuf.mark(); + + // We expect the position of the buffer to be at the + // beginning of a TLS record. Get the type, version and length. + int type = Byte.toUnsignedInt(bBuf.get()); + int ver_major = Byte.toUnsignedInt(bBuf.get()); + int ver_minor = Byte.toUnsignedInt(bBuf.get()); + + log("===== " + header + " (" + tlsRecType(type) + " / " + + ver_major + "." + ver_minor + " / " + + bufLen + " bytes) ====="); + bBuf.reset(); + for (int i = 0; i < bufLen; i++) { + if (i != 0 && i % 16 == 0) { + System.out.print("\n"); + } + System.out.format("%02X ", bBuf.get(i)); + } + log("\n==============================================="); + bBuf.reset(); + } + } +} diff --git a/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java b/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java index 24ff8e08448..48a7c19df74 100644 --- a/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java +++ b/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java @@ -52,21 +52,21 @@ * produced. */ public class SSLEngineTemplate implements SSLContextTemplate { - private final SSLEngine clientEngine; // client Engine - private final ByteBuffer clientOut; // write side of clientEngine - private final ByteBuffer clientIn; // read side of clientEngine + protected final SSLEngine clientEngine; // client Engine + protected final ByteBuffer clientOut; // write side of clientEngine + protected final ByteBuffer clientIn; // read side of clientEngine - private final SSLEngine serverEngine; // server Engine - private final ByteBuffer serverOut; // write side of serverEngine - private final ByteBuffer serverIn; // read side of serverEngine + protected final SSLEngine serverEngine; // server Engine + protected final ByteBuffer serverOut; // write side of serverEngine + protected final ByteBuffer serverIn; // read side of serverEngine // For data transport, this example uses local ByteBuffers. This // isn't really useful, but the purpose of this example is to show // SSLEngine concepts, not how to do network transport. - private final ByteBuffer cTOs; // "reliable" transport client->server - private final ByteBuffer sTOc; // "reliable" transport server->client + protected final ByteBuffer cTOs; // "reliable" transport client->server + protected final ByteBuffer sTOc; // "reliable" transport server->client - private SSLEngineTemplate() throws Exception { + protected SSLEngineTemplate() throws Exception { serverEngine = configureServerEngine( createServerSSLContext().createSSLEngine()); @@ -223,7 +223,7 @@ private static void log(String message) { // If the result indicates that we have outstanding tasks to do, // go ahead and run them in this thread. - private static void runDelegatedTasks(SSLEngine engine) throws Exception { + protected static void runDelegatedTasks(SSLEngine engine) throws Exception { if (engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable; while ((runnable = engine.getDelegatedTask()) != null) { From f90271145181dfe47b80b20649493d89dc9b62eb Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 27 May 2026 14:36:53 +0200 Subject: [PATCH 7/8] Backport 7441d3877f19c2c891ddddaba42f0819813f41eb 8263188: JSSE should fail fast if there isn't supported signature algorithm --- .../sun/security/ssl/CertificateRequest.java | 17 +- .../ssl/SignatureAlgorithmsExtension.java | 10 +- .../net/ssl/templates/SSLContextTemplate.java | 6 +- .../net/ssl/templates/SSLEngineTemplate.java | 4 +- .../SigAlgosExtTestWithTLS12.java | 393 ++++++++++++++++++ .../SigAlgosExtTestWithTLS13.java | 89 ++++ 6 files changed, 506 insertions(+), 13 deletions(-) create mode 100644 jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java create mode 100644 jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java diff --git a/jdk/src/share/classes/sun/security/ssl/CertificateRequest.java b/jdk/src/share/classes/sun/security/ssl/CertificateRequest.java index 475ec42ce0e..85c7716d691 100644 --- a/jdk/src/share/classes/sun/security/ssl/CertificateRequest.java +++ b/jdk/src/share/classes/sun/security/ssl/CertificateRequest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -706,13 +706,16 @@ public void consume(ConnectionContext context, chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id, SSLHandshake.CERTIFICATE); - List sss = new LinkedList<>(); - for (int id : crm.algorithmIds) { - SignatureScheme ss = SignatureScheme.valueOf(id); - if (ss != null) { - sss.add(ss); - } + List sss = + SignatureScheme.getSupportedAlgorithms( + chc.sslConfig, + chc.algorithmConstraints, chc.negotiatedProtocol, + crm.algorithmIds); + if (sss == null || sss.isEmpty()) { + throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); } + chc.peerRequestedSignatureSchemes = sss; chc.peerRequestedCertSignSchemes = sss; // use the same schemes chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss); diff --git a/jdk/src/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java b/jdk/src/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java index 2bea2a6eeba..b0184ccd76e 100644 --- a/jdk/src/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java +++ b/jdk/src/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java @@ -282,6 +282,10 @@ public void consume(ConnectionContext context, shc.sslConfig, shc.algorithmConstraints, shc.negotiatedProtocol, spec.signatureSchemes); + if (sss == null || sss.isEmpty()) { + throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); + } shc.peerRequestedSignatureSchemes = sss; // If no "signature_algorithms_cert" extension is present, then @@ -333,7 +337,7 @@ public void absent(ConnectionContext context, if (shc.negotiatedProtocol.useTLS13PlusSpec()) { throw shc.conContext.fatal(Alert.MISSING_EXTENSION, "No mandatory signature_algorithms extension in the " + - "received CertificateRequest handshake message"); + "received ClientHello handshake message"); } } } @@ -519,6 +523,10 @@ public void consume(ConnectionContext context, chc.sslConfig, chc.algorithmConstraints, chc.negotiatedProtocol, spec.signatureSchemes); + if (sss == null || sss.isEmpty()) { + throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); + } chc.peerRequestedSignatureSchemes = sss; // If no "signature_algorithms_cert" extension is present, then diff --git a/jdk/test/javax/net/ssl/templates/SSLContextTemplate.java b/jdk/test/javax/net/ssl/templates/SSLContextTemplate.java index cdd4e97b407..d072b9d991f 100644 --- a/jdk/test/javax/net/ssl/templates/SSLContextTemplate.java +++ b/jdk/test/javax/net/ssl/templates/SSLContextTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -478,7 +478,7 @@ default SSLContext createSSLContext( /* * Create an instance of KeyManager with the specified key materials. */ - default KeyManager createKeyManager( + static KeyManager createKeyManager( String[] keyMaterialCerts, String[] keyMaterialKeys, String[] keyMaterialKeyAlgs, @@ -534,7 +534,7 @@ default KeyManager createKeyManager( /* * Create an instance of TrustManager with the specified trust materials. */ - default TrustManager createTrustManager( + static TrustManager createTrustManager( String[] trustedMaterials, ContextParameters params) throws Exception { diff --git a/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java b/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java index 48a7c19df74..621aaea3546 100644 --- a/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java +++ b/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java @@ -197,7 +197,7 @@ private void runTest() throws Exception { } } - private static boolean isOpen(SSLEngine engine) { + static boolean isOpen(SSLEngine engine) { return (!engine.isOutboundDone() || !engine.isInboundDone()); } @@ -240,7 +240,7 @@ protected static void runDelegatedTasks(SSLEngine engine) throws Exception { } // Simple check to make sure everything came across as expected. - private static void checkTransfer(ByteBuffer a, ByteBuffer b) + static void checkTransfer(ByteBuffer a, ByteBuffer b) throws Exception { a.flip(); b.flip(); diff --git a/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java b/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java new file mode 100644 index 00000000000..f7eb7cf3e91 --- /dev/null +++ b/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2021, Tencent. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 8263188 + * @summary If TLS the server and client has no common signature algorithms, + * the connection should fail fast with "No supported signature algorithm". + * This test only covers TLS 1.2. + * + * @library /test/lib + * /javax/net/ssl/templates + * + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256,ecdsa_secp384r1_sha384 + * -Dtest.clientAuth=false + * -Dtest.expectFail=false + * SigAlgosExtTestWithTLS12 + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Dtest.clientAuth=false + * -Dtest.expectFail=true + * SigAlgosExtTestWithTLS12 + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Dtest.clientAuth=true + * -Dtest.expectFail=true + * SigAlgosExtTestWithTLS12 + */ + +import javax.net.ssl.*; +import java.nio.ByteBuffer; +import java.util.*; + +public class SigAlgosExtTestWithTLS12 extends SSLEngineTemplate { + + private static final boolean CLIENT_AUTH + = Boolean.getBoolean("test.clientAuth"); + private static final boolean EXPECT_FAIL + = Boolean.getBoolean("test.expectFail"); + + private static final String[] CA_CERTS = new String[] { + // SHA256withECDSA, curve secp256r1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Subject Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" + + "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" + + "LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" + + "A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" + + "MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" + + "6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" + + "2YEHlSQUAbwwqCDEVB5KxaqP\n" + + "-----END CERTIFICATE-----", + + // SHA384withECDSA, curve secp384r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Subject Key Identifier: + // 0a:93:a9:a0:bf:e7:d5:48:9d:4f:89:15:c6:51:98:80:05:51:4e:4e + "-----BEGIN CERTIFICATE-----\n" + + "MIICCDCCAY6gAwIBAgIUCpOpoL/n1UidT4kVxlGYgAVRTk4wCgYIKoZIzj0EAwMw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowOzEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENVQN1wXWFdgC6u/dDdiC\n" + + "y+WtMTF66oL/0BSm+1ZqsogamzCryawOcHgiuXgWzx5CQ3LuOC+tDFyXpGfHuCvb\n" + + "dkzxPrP5n9NrR8/uRPe5l1KOUbchviU8z9cTP+LZxnZDo1MwUTAdBgNVHQ4EFgQU\n" + + "SktSFArR1p/5mXV0kyo0RxIVa/UwHwYDVR0jBBgwFoAUSktSFArR1p/5mXV0kyo0\n" + + "RxIVa/UwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjBZvoNmq3/v\n" + + "RD2gBTyvxjS9h0rsMRLHDnvul/KWngytwGPTOBo0Y8ixQXSjdKoc3rkCMQDkiNgx\n" + + "IDxuHedmrLQKIPnVcthTmwv7//jHiqGoKofwChMo2a1P+DQdhszmeHD/ARQ=\n" + + "-----END CERTIFICATE-----" + }; + + private static final String[] EE_CERTS = new String[] { + // SHA256withECDSA, curve secp256r1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Authority Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" + + "MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" + + "QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" + + "xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" + + "SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" + + "1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" + + "-----END CERTIFICATE-----", + + // SHA384withECDSA, curve secp384r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Authority Key Identifier: + // 40:2D:AA:EE:66:AA:33:27:AD:9B:5D:52:9B:60:67:6A:2B:AD:52:D2 + "-----BEGIN CERTIFICATE-----\n" + + "MIICEjCCAZegAwIBAgIUS3F0AqAXWRg07CnbknJzxofyBQMwCgYIKoZIzj0EAwMw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowVTEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMRgwFgYDVQQDDA9SZWdyZXNzaW9uIFRlc3QwdjAQBgcqhkjOPQIB\n" + + "BgUrgQQAIgNiAARqElz8b6T07eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/w\n" + + "G8ASSevpgqgpi6EzpBZaaJxE3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEj\n" + + "iLjYmt3O0pwpklijQjBAMB0GA1UdDgQWBBRALaruZqozJ62bXVKbYGdqK61S0jAf\n" + + "BgNVHSMEGDAWgBRKS1IUCtHWn/mZdXSTKjRHEhVr9TAKBggqhkjOPQQDAwNpADBm\n" + + "AjEArVDFKf48xijN6huVUJzKCOP0zlWB5Js+DItIkZmLQuhciPLhLIB/rChf3Y4C\n" + + "xuP4AjEAmfLhQRI0O3pifpYzYSVh2G7/jHNG4eO+2dvgAcU+Lh2IIj/cpLaPFSvL\n" + + "J8FXY9Nj\n" + + "-----END CERTIFICATE-----" + }; + + private static final String[] EE_KEYS = new String[] { + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" + + "JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" + + "59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6", + "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDASuI9EtK29APXPipkc\n" + + "qDA+qwlewMjv/OcjUJ77kP1Vz62oVF9iY9SRIyFIUju8wt+hZANiAARqElz8b6T0\n" + + "7eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/wG8ASSevpgqgpi6EzpBZaaJxE\n" + + "3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEjiLjYmt3O0pwpklg=" + }; + + private static final String[] EE_ALGS = new String[] { + "EC", + "EC" + }; + + private static final String[] EE_ALIASES = new String[] { + "EC-SHA256", + "EC-SHA384" + }; + + private static final Map SIG_SCHEMES_MAP = Map.of( + 0x0403, "ecdsa_secp256r1_sha256", + 0x0503, "ecdsa_secp384r1_sha384"); + + private static final int TLS_HS_CLI_HELLO = 1; + private static final int TLS_HS_CERT_REQ = 13; + private static final int HELLO_EXT_SIG_ALGS = 13; + + public SigAlgosExtTestWithTLS12() throws Exception { + super(); + } + + /* + * Create an instance of KeyManager for client use. + */ + public KeyManager createClientKeyManager() throws Exception { + return SSLContextTemplate.createKeyManager( + EE_CERTS, + EE_KEYS, + EE_ALGS, + EE_ALIASES, + getServerContextParameters()); + } + + @Override + public TrustManager createClientTrustManager() throws Exception { + return SSLContextTemplate.createTrustManager( + CA_CERTS, + getServerContextParameters()); + } + + @Override + public KeyManager createServerKeyManager() throws Exception { + return SSLContextTemplate.createKeyManager( + EE_CERTS, + EE_KEYS, + EE_ALGS, + EE_ALIASES, + getServerContextParameters()); + } + + @Override + public TrustManager createServerTrustManager() throws Exception { + return SSLContextTemplate.createTrustManager( + CA_CERTS, + getServerContextParameters()); + } + + @Override + protected SSLEngine configureServerEngine(SSLEngine serverEngine) { + serverEngine.setUseClientMode(false); + serverEngine.setNeedClientAuth(CLIENT_AUTH); + return serverEngine; + } + + @Override + protected SSLEngine configureClientEngine(SSLEngine clientEngine) { + clientEngine.setUseClientMode(true); + clientEngine.setEnabledProtocols(new String[] { "TLSv1.2" }); + return clientEngine; + } + + public static void main(String[] args) throws Exception { + System.setProperty("javax.net.debug", "ssl:handshake"); + + try { + new SigAlgosExtTestWithTLS12().run(); + if (EXPECT_FAIL) { + throw new RuntimeException( + "Expected SSLHandshakeException wasn't thrown"); + } + } catch (SSLHandshakeException e) { + if (EXPECT_FAIL && e.getMessage().equals( + "No supported signature algorithm")) { + System.out.println("Expected SSLHandshakeException"); + } else { + throw e; + } + } + } + + private void run() throws Exception { + boolean dataDone = false; + while (isOpen(clientEngine) || isOpen(serverEngine)) { + clientEngine.wrap(clientOut, cTOs); + cTOs.flip(); + + // Consume the ClientHello and get the server flight of handshake + // messages. We expect that it will be one TLS record containing + // multiple handshake messages, one of which is a CertificateRequest + // when the client authentication is required. + serverEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverEngine); + + // Wrap the server flight + serverEngine.wrap(serverOut, sTOc); + sTOc.flip(); + + if (CLIENT_AUTH && EXPECT_FAIL) { + twistCertReqMsg(sTOc); + } + + clientEngine.unwrap(sTOc, clientIn); + runDelegatedTasks(clientEngine); + + serverEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverEngine); + + cTOs.compact(); + sTOc.compact(); + + if (!dataDone && (clientOut.limit() == serverIn.position()) && + (serverOut.limit() == clientIn.position())) { + checkTransfer(serverOut, clientIn); + checkTransfer(clientOut, serverIn); + + clientEngine.closeOutbound(); + dataDone = true; + serverEngine.closeOutbound(); + } + } + } + + /** + * Twists signature schemes in CertificateRequest message for negative + * client authentication cases. + * + * @param tlsRecord a ByteBuffer containing a TLS record. It is assumed + * that the position of the ByteBuffer is on the first byte of the TLS + * record header. + * + * @throws SSLException if the incoming ByteBuffer does not contain a + * well-formed TLS message. + */ + private static void twistCertReqMsg( + ByteBuffer tlsRecord) throws SSLException { + Objects.requireNonNull(tlsRecord); + tlsRecord.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(tlsRecord.get()); + int ver_major = Byte.toUnsignedInt(tlsRecord.get()); + int ver_minor = Byte.toUnsignedInt(tlsRecord.get()); + int recLen = Short.toUnsignedInt(tlsRecord.getShort()); + + // Simple sanity checks + if (type != 22) { + throw new SSLException("Not a handshake: Type = " + type); + } else if (recLen > tlsRecord.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + ", Remaining = " + + tlsRecord.remaining()); + } + + while (tlsRecord.hasRemaining()) { + // Grab the handshake message header. + int msgHdr = tlsRecord.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + + if (msgType == TLS_HS_CERT_REQ) { + // Slice the buffer such that it contains the entire + // handshake message (less the handshake header). + int bufPos = tlsRecord.position(); + ByteBuffer buf = slice(tlsRecord, bufPos, msgLen); + + // Replace the signature scheme with an unknown value + twistSigSchemesCertReq(buf, (short) 0x0000); + byte[] bufBytes = new byte[buf.limit()]; + buf.get(bufBytes); + tlsRecord.position(bufPos).put(bufBytes); + + break; + } else { + // Skip to the next handshake message, if there is one + tlsRecord.position(tlsRecord.position() + msgLen); + } + } + + tlsRecord.reset(); + } + + /* Implementation of ByteBuffer.slice(int, int) for JDK11 */ + private static final ByteBuffer slice(ByteBuffer buffer, int index, int length) { + final int limit = buffer.limit(); + final int position = buffer.position(); + buffer.position(index); + buffer.limit(index + length); + ByteBuffer slice = buffer.slice(); + buffer.limit(limit); + buffer.position(position); + return slice; + } + + /** + * Replace the signature schemes in CertificateRequest message with an + * alternative value. It is assumed that the provided ByteBuffer has its + * position set at the first byte of the CertificateRequest message body + * (AFTER the handshake header) and contains the entire CR message. Upon + * successful completion of this method the ByteBuffer will have its + * position reset to the initial offset in the buffer. + * If an exception is thrown the position at the time of the exception + * will be preserved. + * + * @param data the ByteBuffer containing the CertificateRequest bytes + * @param altSigScheme an alternative signature scheme + */ + private static void twistSigSchemesCertReq(ByteBuffer data, + Short altSigScheme) { + Objects.requireNonNull(data); + data.mark(); + + // Jump past the certificate types + int certTypeLen = Byte.toUnsignedInt(data.get()); + if (certTypeLen != 0) { + data.position(data.position() + certTypeLen); + } + + int sigSchemeLen = Short.toUnsignedInt(data.getShort()); + for (int ssOff = 0; ssOff < sigSchemeLen; ssOff += 2) { + System.err.println( + "Use alternative signature scheme: " + altSigScheme); + data.putShort(data.position(), altSigScheme); + } + + data.reset(); + } +} diff --git a/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java b/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java new file mode 100644 index 00000000000..c4784c09da8 --- /dev/null +++ b/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021, Tencent. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 8263188 + * @summary If TLS the server and client has no common signature algorithms, + * the connection should fail fast with "No supported signature algorithm". + * This test only covers TLS 1.3, but doesn't cover client authentication. + * + * @library /test/lib + * /javax/net/ssl/templates + * + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256,ecdsa_secp384r1_sha384 + * -Dtest.expectFail=false + * SigAlgosExtTestWithTLS13 + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Dtest.expectFail=true + * SigAlgosExtTestWithTLS13 + */ + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLSocket; + +public class SigAlgosExtTestWithTLS13 extends SSLSocketTemplate { + + @Override + protected SSLContext createServerSSLContext() throws Exception { + return createSSLContext( + new Cert[] { Cert.CA_ECDSA_SECP256R1, Cert.CA_ECDSA_SECP384R1 }, + new Cert[] { Cert.EE_ECDSA_SECP256R1, Cert.EE_ECDSA_SECP384R1 }, + getServerContextParameters()); + } + + @Override + protected SSLContext createClientSSLContext() throws Exception { + return createSSLContext( + new Cert[] { Cert.CA_ECDSA_SECP256R1, Cert.CA_ECDSA_SECP384R1 }, + new Cert[] { Cert.EE_ECDSA_SECP256R1, Cert.EE_ECDSA_SECP384R1 }, + getClientContextParameters()); + } + + @Override + protected void configureClientSocket(SSLSocket socket) { + socket.setEnabledProtocols(new String[] { "TLSv1.3" }); + } + + public static void main(String[] args) throws Exception { + boolean expectFail = Boolean.getBoolean("test.expectFail"); + try { + new SigAlgosExtTestWithTLS13().run(); + if (expectFail) { + throw new RuntimeException( + "Expected SSLHandshakeException wasn't thrown"); + } + } catch (SSLHandshakeException e) { + if (expectFail && e.getMessage().equals( + "No supported signature algorithm")) { + System.out.println("Expected SSLHandshakeException"); + } else { + throw e; + } + } + } +} From 01fd4427e29f6e8dcdb4ece188c911629a791885 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 27 May 2026 20:34:00 +0200 Subject: [PATCH 8/8] Fix SigAlgosExtTestWithTLS12 for 8u --- .../SignatureScheme/SigAlgosExtTestWithTLS12.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java b/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java index f7eb7cf3e91..7bc056fdca1 100644 --- a/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java +++ b/jdk/test/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java @@ -163,9 +163,14 @@ public class SigAlgosExtTestWithTLS12 extends SSLEngineTemplate { "EC-SHA384" }; - private static final Map SIG_SCHEMES_MAP = Map.of( - 0x0403, "ecdsa_secp256r1_sha256", - 0x0503, "ecdsa_secp384r1_sha384"); + private static final Map SIG_SCHEMES_MAP; + + static { + Map tempMap = new HashMap<>(); + tempMap.put(0x0403, "ecdsa_secp256r1_sha256"); + tempMap.put(0x0503, "ecdsa_secp384r1_sha384"); + SIG_SCHEMES_MAP = Collections.unmodifiableMap(tempMap); + } private static final int TLS_HS_CLI_HELLO = 1; private static final int TLS_HS_CERT_REQ = 13; @@ -333,7 +338,7 @@ private static void twistCertReqMsg( twistSigSchemesCertReq(buf, (short) 0x0000); byte[] bufBytes = new byte[buf.limit()]; buf.get(bufBytes); - tlsRecord.position(bufPos).put(bufBytes); + ((ByteBuffer)tlsRecord.position(bufPos)).put(bufBytes); break; } else {