Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/security/ssl/DHKeyExchange/DHEKeySizing.java
38853 views
/*1* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223//24// SunJSSE does not support dynamic system properties, no way to re-use25// system properties in samevm/agentvm mode.26//2728/*29* @test30* @bug 695639831* @summary make ephemeral DH key match the length of the certificate key32* @run main/othervm33* DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1643 26734* @run main/othervm -Djsse.enableFFDHE=false35* DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1259 7536* @run main/othervm -Djsse.enableFFDHE=false37* -Djdk.tls.ephemeralDHKeySize=matched38* DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1259 7539* @run main/othervm -Djsse.enableFFDHE=false40* -Djdk.tls.ephemeralDHKeySize=legacy41* DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1259 7542* @run main/othervm -Djsse.enableFFDHE=false43* -Djdk.tls.ephemeralDHKeySize=102444* DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1259 7545*46* @run main/othervm -Djsse.enableFFDHE=false47* DHEKeySizing SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA true 233 7548*49* @run main/othervm -Djsse.enableFFDHE=false50* DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1387 13951* @run main/othervm -Djsse.enableFFDHE=false52* -Djdk.tls.ephemeralDHKeySize=legacy53* DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1323 10754* @run main/othervm -Djsse.enableFFDHE=false55* -Djdk.tls.ephemeralDHKeySize=matched56* DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1643 26757* @run main/othervm -Djsse.enableFFDHE=false58* -Djdk.tls.ephemeralDHKeySize=102459* DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1387 13960*61* @run main/othervm -Djsse.enableFFDHE=false62* DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 361 13963* @run main/othervm -Djsse.enableFFDHE=false64* -Djdk.tls.ephemeralDHKeySize=legacy65* DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 297 10766* @run main/othervm -Djsse.enableFFDHE=false67* -Djdk.tls.ephemeralDHKeySize=matched68* DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 361 13969* @run main/othervm -Djsse.enableFFDHE=false70* -Djdk.tls.ephemeralDHKeySize=102471* DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 361 13972*/7374/*75* This is a simple hack to test key sizes of Diffie-Hellman key exchanging76* during SSL/TLS handshaking.77*78* The record length of DH ServerKeyExchange and ClientKeyExchange.79* ServerKeyExchange message are wrapped in ServerHello series messages, which80* contains ServerHello, Certificate and ServerKeyExchange message.81*82* struct {83* opaque dh_p<1..2^16-1>;84* opaque dh_g<1..2^16-1>;85* opaque dh_Ys<1..2^16-1>;86* } ServerDHParams; // Ephemeral DH parameters87*88* struct {89* select (PublicValueEncoding) {90* case implicit: struct { };91* case explicit: opaque dh_Yc<1..2^16-1>;92* } dh_public;93* } ClientDiffieHellmanPublic;94*95* Fomr above structures, it is clear that if the DH key size increasing 12896* bits (16 bytes), the ServerHello series messages increases 48 bytes97* (becuase dh_p, dh_g and dh_Ys each increase 16 bytes) and ClientKeyExchange98* increases 16 bytes (because of the size increasing of dh_Yc).99*100* Here is a summary of the record length in the test case.101*102* | ServerHello Series | ClientKeyExchange | ServerHello Anon103* 512-bit | 1259 bytes | 75 bytes | 233 bytes104* 768-bit | 1323 bytes | 107 bytes | 297 bytes105* 1024-bit | 1387 bytes | 139 bytes | 361 bytes106* 2048-bit | 1643 bytes | 267 bytes | 361 bytes107*/108109import javax.net.ssl.*;110import javax.net.ssl.SSLEngineResult.*;111import java.io.*;112import java.nio.*;113import java.security.KeyStore;114import java.security.KeyFactory;115import java.security.Security;116import java.security.cert.Certificate;117import java.security.cert.CertificateFactory;118import java.security.spec.PKCS8EncodedKeySpec;119import java.security.interfaces.*;120import java.util.Base64;121122public class DHEKeySizing {123124private final static boolean debug = true;125126// key length bias because of the stripping of leading zero bytes of127// negotiated DH keys.128//129// This is an effort to mimum intermittent failure when we cannot130// estimate what's the exact number of leading zero bytes of131// negotiated DH keys.132private final static int KEY_LEN_BIAS = 6;133134private SSLContext sslc;135private SSLEngine ssle1; // client136private SSLEngine ssle2; // server137138private ByteBuffer appOut1; // write side of ssle1139private ByteBuffer appIn1; // read side of ssle1140private ByteBuffer appOut2; // write side of ssle2141private ByteBuffer appIn2; // read side of ssle2142143private ByteBuffer oneToTwo; // "reliable" transport ssle1->ssle2144private ByteBuffer twoToOne; // "reliable" transport ssle2->ssle1145146/*147* Where do we find the keystores?148*/149// Certificates and key used in the test.150static String trustedCertStr =151"-----BEGIN CERTIFICATE-----\n" +152"MIIC8jCCAdqgAwIBAgIEUjkuRzANBgkqhkiG9w0BAQUFADA7MR0wGwYDVQQLExRT\n" +153"dW5KU1NFIFRlc3QgU2VyaXZjZTENMAsGA1UEChMESmF2YTELMAkGA1UEBhMCVVMw\n" +154"HhcNMTMwOTE4MDQzODMxWhcNMTMxMjE3MDQzODMxWjA7MR0wGwYDVQQLExRTdW5K\n" +155"U1NFIFRlc3QgU2VyaXZjZTENMAsGA1UEChMESmF2YTELMAkGA1UEBhMCVVMwggEi\n" +156"MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCO+IGeaskJAvEcYc7pCl9neK3E\n" +157"a28fwWLtChufYNaC9hQfZlUdETWYjV7fZJVJKT/oLzdDNMWuVA0LKXArpI3thLNK\n" +158"QLXisdF9hKPlZRDazACL9kWUUtJ0FzpEySK4e8wW/z9FuU6e6iO19FbjxAfInJqk\n" +159"3EDiEhB5g73S2vtvPCxgq2DvWw9TDl/LIqdKG2JCS93koXCCaHmQ7MrIOqHPd+8r\n" +160"RbGpatXT9qyHKppUv9ATxVygO4rA794mgCFxpT+fkhz+NEB0twTkM65T1hnnOv5n\n" +161"ZIxkcjBggt85UlZtnP3b9P7SYxsWIa46Oc38Od2f3YejfVg6B+PqPgWNl3+/AgMB\n" +162"AAEwDQYJKoZIhvcNAQEFBQADggEBAAlrP6DFLRPSy0IgQhcI2i56tR/na8pezSte\n" +163"ZHcCdaCZPDy4UP8mpLJ9QCjEB5VJv8hPm4xdK7ULnKGOGHgYqDpV2ZHvQlhV1woQ\n" +164"TZGb/LM3c6kAs0j4j9KM2fq3iYUYexjIkS1KzsziflxMM6igS9BRMBR2LQyU+cYq\n" +165"YEsFzkF7Aj2ET4v/+tgot9mRr2NioJcaJkdsPDpMU3IKB1cczfu+OuLQ/GCG0Fqu\n" +166"6ijCeCqfnaAbemHbJeVZZ6Qgka3uC2YMntLBmLkhqEo1d9zGYLoh7oWL77y5ibQZ\n" +167"LK5/H/zikcu579TWjlDHcqL3arCwBcrtsjSaPrRSWMrWV/6c0qw=\n" +168"-----END CERTIFICATE-----";169170// Private key in the format of PKCS#8171static String targetPrivateKey =172"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCO+IGeaskJAvEc\n" +173"Yc7pCl9neK3Ea28fwWLtChufYNaC9hQfZlUdETWYjV7fZJVJKT/oLzdDNMWuVA0L\n" +174"KXArpI3thLNKQLXisdF9hKPlZRDazACL9kWUUtJ0FzpEySK4e8wW/z9FuU6e6iO1\n" +175"9FbjxAfInJqk3EDiEhB5g73S2vtvPCxgq2DvWw9TDl/LIqdKG2JCS93koXCCaHmQ\n" +176"7MrIOqHPd+8rRbGpatXT9qyHKppUv9ATxVygO4rA794mgCFxpT+fkhz+NEB0twTk\n" +177"M65T1hnnOv5nZIxkcjBggt85UlZtnP3b9P7SYxsWIa46Oc38Od2f3YejfVg6B+Pq\n" +178"PgWNl3+/AgMBAAECggEAPdb5Ycc4m4A9QBSCRcRpzbyiFLKPh0HDg1n65q4hOtYr\n" +179"kAVYTVFTSF/lqGS+Ob3w2YIKujQKSUQrvCc5UHdFuHXMgxKIWbymK0+DAMb9SlYw\n" +180"6lkkcWp9gx9E4dnJ/df2SAAxovvrKMuHlL1SFASHhVtPfH2URvSfUaANLDXxyYOs\n" +181"8BX0Nr6wazhWjLjXo9yIGnKSvFfB8XisYcA78kEgas43zhmIGCDPqaYyyffOfRbx\n" +182"pM1KNwGmlN86iWR1CbwA/wwhcMySWQueS+s7cHbpRqZIYJF9jEeELiwi0vxjealS\n" +183"EMuHYedIRFMWaDIq9XyjrvXamHb0Z25jlXBNZHaM0QKBgQDE9adl+zAezR/n79vw\n" +184"0XiX2Fx1UEo3ApZHuoA2Q/PcBk+rlKqqQ3IwTcy6Wo648wK7v6Nq7w5nEWcsf0dU\n" +185"QA2Ng/AJEev/IfF34x7sKGYxtk1gcE0EuSBA3R+ocEZxnNw1Ryd5nUU24s8d4jCP\n" +186"Mkothnyaim+zE2raDlEtVc0CaQKBgQC509av+02Uq5oMjzbQp5PBJfQFjATOQT15\n" +187"eefYnVYurkQ1kcVfixkrO2ORhg4SjmI2Z5hJDgGtXdwgidpzkad+R2epS5qLMyno\n" +188"lQVpY6bMpEZ7Mos0yQygxnm8uNohEcTExOe+nP5fNJVpzBsGmfeyYOhnPQlf6oqf\n" +189"0cHizedb5wKBgQC/l5LyMil6HOGHlhzmIm3jj7VI7QR0hJC5T6N+phVml8ESUDjA\n" +190"DYHbmSKouISTRtkG14FY+RiSjCxH7bvuKazFV2289PETquogTA/9e8MFYqfcQwG4\n" +191"sXi9gBxWlnj/9a2EKiYtOB5nKLR/BlNkSHA93tAA6N+FXEMZwMmYhxk42QKBgAuY\n" +192"HQgD3PZOsqDf+qKQIhbmAFCsSMx5o5VFtuJ8BpmJA/Z3ruHkMuDQpsi4nX4o5hXQ\n" +193"5t6AAjjH52kcUMXvK40kdWJJtk3DFnVNfvXxYsHX6hHbuHXFqYUKfSP6QJnZmvZP\n" +194"9smcz/4usLfWJUWHK740b6upUkFqx9Vq5/b3s9y3AoGAdM5TW7LkkOFsdMGVAUzR\n" +195"9iXmCWElHTK2Pcp/3yqDBHSfiQx6Yp5ANyPnE9NBM0yauCfOyBB2oxLO4Rdv3Rqk\n" +196"9V9kyR/YAGr7dJaPcQ7pZX0OpkzgueAOJYPrx5VUzPYUtklYV1ycFZTfKlpFCxT+\n" +197"Ei6KUo0NXSdUIcB4yib1J10=";198199static char passphrase[] = "passphrase".toCharArray();200201/*202* Majority of the test case is here, setup is done below.203*/204205private void createSSLEngines() throws Exception {206ssle1 = sslc.createSSLEngine("client", 1);207ssle1.setUseClientMode(true);208209ssle2 = sslc.createSSLEngine("server", 2);210ssle2.setUseClientMode(false);211}212213private boolean isHandshaking(SSLEngine e) {214return (e.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING);215}216217private void checkResult(ByteBuffer bbIn, ByteBuffer bbOut,218SSLEngineResult result,219Status status, HandshakeStatus hsStatus,220int consumed, int produced)221throws Exception {222223if ((status != null) && (result.getStatus() != status)) {224throw new Exception("Unexpected Status: need = " + status +225" got = " + result.getStatus());226}227228if ((hsStatus != null) && (result.getHandshakeStatus() != hsStatus)) {229throw new Exception("Unexpected hsStatus: need = " + hsStatus +230" got = " + result.getHandshakeStatus());231}232233if ((consumed != -1) && (consumed != result.bytesConsumed())) {234throw new Exception("Unexpected consumed: need = " + consumed +235" got = " + result.bytesConsumed());236}237238if ((produced != -1) && (produced != result.bytesProduced())) {239throw new Exception("Unexpected produced: need = " + produced +240" got = " + result.bytesProduced());241}242243if ((consumed != -1) && (bbIn.position() != result.bytesConsumed())) {244throw new Exception("Consumed " + bbIn.position() +245" != " + consumed);246}247248if ((produced != -1) && (bbOut.position() != result.bytesProduced())) {249throw new Exception("produced " + bbOut.position() +250" != " + produced);251}252}253254private void test(String cipherSuite, boolean exportable,255int lenServerKeyEx, int lenClientKeyEx) throws Exception {256257createSSLEngines();258createBuffers();259260SSLEngineResult result1; // ssle1's results from last operation261SSLEngineResult result2; // ssle2's results from last operation262263String[] suites = new String [] {cipherSuite};264265ssle1.setEnabledCipherSuites(suites);266ssle2.setEnabledCipherSuites(suites);267268log("======================================");269log("===================");270log("client hello");271result1 = ssle1.wrap(appOut1, oneToTwo);272checkResult(appOut1, oneToTwo, result1,273Status.OK, HandshakeStatus.NEED_UNWRAP, 0, -1);274oneToTwo.flip();275276result2 = ssle2.unwrap(oneToTwo, appIn2);277checkResult(oneToTwo, appIn2, result2,278Status.OK, HandshakeStatus.NEED_TASK, result1.bytesProduced(), 0);279runDelegatedTasks(ssle2);280oneToTwo.compact();281282log("===================");283log("ServerHello");284result2 = ssle2.wrap(appOut2, twoToOne);285checkResult(appOut2, twoToOne, result2,286Status.OK, HandshakeStatus.NEED_UNWRAP, 0, -1);287twoToOne.flip();288289log("Message length of ServerHello series: " + twoToOne.remaining());290if (twoToOne.remaining() < (lenServerKeyEx - KEY_LEN_BIAS) ||291twoToOne.remaining() > lenServerKeyEx) {292throw new Exception(293"Expected to generate ServerHello series messages of " +294lenServerKeyEx + " bytes, but not " + twoToOne.remaining());295}296297result1 = ssle1.unwrap(twoToOne, appIn1);298checkResult(twoToOne, appIn1, result1,299Status.OK, HandshakeStatus.NEED_TASK, result2.bytesProduced(), 0);300runDelegatedTasks(ssle1);301twoToOne.compact();302303log("===================");304log("Key Exchange");305result1 = ssle1.wrap(appOut1, oneToTwo);306checkResult(appOut1, oneToTwo, result1,307Status.OK, HandshakeStatus.NEED_WRAP, 0, -1);308oneToTwo.flip();309310log("Message length of ClientKeyExchange: " + oneToTwo.remaining());311if (oneToTwo.remaining() < (lenClientKeyEx - KEY_LEN_BIAS) ||312oneToTwo.remaining() > lenClientKeyEx) {313throw new Exception(314"Expected to generate ClientKeyExchange message of " +315lenClientKeyEx + " bytes, but not " + oneToTwo.remaining());316}317result2 = ssle2.unwrap(oneToTwo, appIn2);318checkResult(oneToTwo, appIn2, result2,319Status.OK, HandshakeStatus.NEED_TASK, result1.bytesProduced(), 0);320runDelegatedTasks(ssle2);321oneToTwo.compact();322323log("===================");324log("Client CCS");325result1 = ssle1.wrap(appOut1, oneToTwo);326checkResult(appOut1, oneToTwo, result1,327Status.OK, HandshakeStatus.NEED_WRAP, 0, -1);328oneToTwo.flip();329330result2 = ssle2.unwrap(oneToTwo, appIn2);331checkResult(oneToTwo, appIn2, result2,332Status.OK, HandshakeStatus.NEED_UNWRAP,333result1.bytesProduced(), 0);334oneToTwo.compact();335336log("===================");337log("Client Finished");338result1 = ssle1.wrap(appOut1, oneToTwo);339checkResult(appOut1, oneToTwo, result1,340Status.OK, HandshakeStatus.NEED_UNWRAP, 0, -1);341oneToTwo.flip();342343result2 = ssle2.unwrap(oneToTwo, appIn2);344checkResult(oneToTwo, appIn2, result2,345Status.OK, HandshakeStatus.NEED_WRAP,346result1.bytesProduced(), 0);347oneToTwo.compact();348349log("===================");350log("Server CCS");351result2 = ssle2.wrap(appOut2, twoToOne);352checkResult(appOut2, twoToOne, result2,353Status.OK, HandshakeStatus.NEED_WRAP, 0, -1);354twoToOne.flip();355356result1 = ssle1.unwrap(twoToOne, appIn1);357checkResult(twoToOne, appIn1, result1,358Status.OK, HandshakeStatus.NEED_UNWRAP, result2.bytesProduced(), 0);359twoToOne.compact();360361log("===================");362log("Server Finished");363result2 = ssle2.wrap(appOut2, twoToOne);364checkResult(appOut2, twoToOne, result2,365Status.OK, HandshakeStatus.FINISHED, 0, -1);366twoToOne.flip();367368result1 = ssle1.unwrap(twoToOne, appIn1);369checkResult(twoToOne, appIn1, result1,370Status.OK, HandshakeStatus.FINISHED, result2.bytesProduced(), 0);371twoToOne.compact();372373log("===================");374log("Check Session/Ciphers");375String cs = ssle1.getSession().getCipherSuite();376if (!cs.equals(suites[0])) {377throw new Exception("suites not equal: " + cs + "/" + suites[0]);378}379380cs = ssle2.getSession().getCipherSuite();381if (!cs.equals(suites[0])) {382throw new Exception("suites not equal: " + cs + "/" + suites[0]);383}384385log("===================");386log("Done with SSL/TLS handshaking");387}388389public static void main(String args[]) throws Exception {390// reset security properties to make sure that the algorithms391// and keys used in this test are not disabled.392Security.setProperty("jdk.tls.disabledAlgorithms", "");393Security.setProperty("jdk.certpath.disabledAlgorithms", "");394395if (args.length != 4) {396System.out.println(397"Usage: java DHEKeySizing cipher-suite " +398"exportable(true|false)\n" +399" size-of-server-hello-record size-of-client-key-exchange");400throw new Exception("Incorrect usage!");401}402403(new DHEKeySizing()).test(args[0],404Boolean.parseBoolean(args[1]),405Integer.parseInt(args[2]),406Integer.parseInt(args[3]));407System.out.println("Test Passed.");408}409410/*411* **********************************************************412* Majority of the test case is above, below is just setup stuff413* **********************************************************414*/415416public DHEKeySizing() throws Exception {417sslc = getSSLContext();418}419420/*421* Create an initialized SSLContext to use for this test.422*/423private SSLContext getSSLContext() throws Exception {424425// generate certificate from cert string426CertificateFactory cf = CertificateFactory.getInstance("X.509");427428// create a key store429KeyStore ts = KeyStore.getInstance("JKS");430KeyStore ks = KeyStore.getInstance("JKS");431ts.load(null, null);432ks.load(null, null);433434// import the trused cert435ByteArrayInputStream is =436new ByteArrayInputStream(trustedCertStr.getBytes());437Certificate trusedCert = cf.generateCertificate(is);438is.close();439ts.setCertificateEntry("rsa-trusted-2048", trusedCert);440441// generate the private key.442String keySpecStr = targetPrivateKey;443PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(444Base64.getMimeDecoder().decode(keySpecStr));445KeyFactory kf = KeyFactory.getInstance("RSA");446RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec);447448Certificate[] chain = new Certificate[1];449chain[0] = trusedCert;450451// import the key entry.452ks.setKeyEntry("rsa-key-2048", priKey, passphrase, chain);453454// create SSL context455KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");456kmf.init(ks, passphrase);457458TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");459tmf.init(ts);460461SSLContext sslCtx = SSLContext.getInstance("TLSv1");462sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);463464return sslCtx;465}466467private void createBuffers() {468// Size the buffers as appropriate.469470SSLSession session = ssle1.getSession();471int appBufferMax = session.getApplicationBufferSize();472int netBufferMax = session.getPacketBufferSize();473474appIn1 = ByteBuffer.allocateDirect(appBufferMax + 50);475appIn2 = ByteBuffer.allocateDirect(appBufferMax + 50);476477oneToTwo = ByteBuffer.allocateDirect(netBufferMax);478twoToOne = ByteBuffer.allocateDirect(netBufferMax);479480appOut1 = ByteBuffer.wrap("Hi Engine2, I'm SSLEngine1".getBytes());481appOut2 = ByteBuffer.wrap("Hello Engine1, I'm SSLEngine2".getBytes());482483log("AppOut1 = " + appOut1);484log("AppOut2 = " + appOut2);485log("");486}487488private static void runDelegatedTasks(SSLEngine engine) throws Exception {489490Runnable runnable;491while ((runnable = engine.getDelegatedTask()) != null) {492log("running delegated task...");493runnable.run();494}495}496497private static void log(String str) {498if (debug) {499System.out.println(str);500}501}502}503504505