/* * 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.
*/
// SunJSSE does not support dynamic system properties, no way to re-use // system properties in samevm/agentvm mode. For further debugging output // set the -Djavax.net.debug=ssl:handshake property on the @run lines.
// ClientHello fields finalint version; finalbyte[] random; finalbyte[] sessId; final List<Integer> cipherSuites = new ArrayList<>(); final List<Integer> compressionList = new ArrayList<>(); final Map<Integer,byte[]> extensionMap = new LinkedHashMap<>();
// These are fields built from specific extension data fields we // are interested in for our tests final List<Integer> suppGroups = new ArrayList<>(); final Map<Integer,byte[]> keyShares = new LinkedHashMap<>(); final List<Integer> suppVersions = new ArrayList<>();
/* * If the result indicates that we have outstanding tasks to do, * go ahead and run them in this thread.
*/ privatestaticvoid runDelegatedTasks(SSLEngine engine) throws Exception { if (engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
Runnable runnable; while ((runnable = engine.getDelegatedTask()) != null) {
System.out.println(" running delegated task...");
runnable.run();
}
HandshakeStatus hsStatus = engine.getHandshakeStatus(); if (hsStatus == HandshakeStatus.NEED_TASK) { thrownew Exception( "handshake shouldn't need additional tasks");
}
}
}
/** * Dump a ByteBuffer as a hexdump to stdout. The dumping routine will * start at the current position of the buffer and run to its limit. * After completing the dump, the position will be returned to its * starting point. * * @param data the ByteBuffer to dump to stdout. * * @return the hexdump of the byte array.
*/ privatestatic String dumpHexBytes(ByteBuffer data) {
StringBuilder sb = new StringBuilder(); if (data != null) { int i = 0;
data.mark(); while (data.hasRemaining()) { if (i % 16 == 0 && i != 0) {
sb.append("\n");
}
sb.append(String.format("%02X ", data.get()));
i++;
}
data.reset();
}
// Create and check the ClientHello message
SSLEngineResult clientResult = engine.wrap(clientOut, cTOs);
logResult("client wrap: ", clientResult); if (clientResult.getStatus() != SSLEngineResult.Status.OK) { thrownew RuntimeException("Client wrap got status: " +
clientResult.getStatus());
}
cTOs.flip();
System.out.println("----- ORIGINAL CLIENT HELLO -----\n" +
dumpHexBytes(cTOs));
ClientHello initialCh = new ClientHello(cTOs);
if (!initialCh.suppVersions.contains(TLS_PROT_VER_13)) { thrownew RuntimeException( "Missing TLSv1.3 protocol in supported_versions");
} elseif (!initialCh.keyShares.containsKey(NG_X25519) ||
!initialCh.keyShares.containsKey(NG_SECP256R1)) { thrownew RuntimeException( "Missing one or more expected KeyShares");
}
// Craft the HRR message with the passed-in named group as the // key share named group to request.
ByteBuffer sTOc = buildHRRMessage(initialCh, hrrNamedGroup);
System.out.println("----- SERVER HELLO RETRY REQUEST -----\n" +
dumpHexBytes(sTOc));
// Unwrap the HRR and process it
clientResult = engine.unwrap(sTOc, clientOut);
logResult("client unwrap: ", clientResult); if (clientResult.getStatus() != SSLEngineResult.Status.OK) { thrownew RuntimeException("Client wrap got status: " +
clientResult.getStatus());
}
runDelegatedTasks(engine);
try { // Now we're expecting to reissue the ClientHello, this time // with a secp384r1 share.
cTOs.compact();
clientResult = engine.wrap(clientOut, cTOs);
logResult("client wrap: ", clientResult); if (clientResult.getStatus() != SSLEngineResult.Status.OK) { thrownew RuntimeException("Client wrap got status: " +
clientResult.getStatus());
}
} catch (RuntimeException | SSLException ssle) { if (expectedPass) {
System.out.println("Caught unexpected exception"); throw ssle;
} else {
System.out.println("Caught expected exception: " + ssle);
// Try issuing another wrap call and see if we can get // the Alert out.
clientResult = engine.wrap(clientOut, cTOs);
logResult("client wrap: ", clientResult); if (clientResult.getStatus() != SSLEngineResult.Status.CLOSED) { thrownew RuntimeException("Client wrap got status: " +
clientResult.getStatus());
}
if (!reissuedCh.keyShares.containsKey(hrrNamedGroup)) { thrownew RuntimeException("Missing secp384r1 key share");
}
}
privatestatic ByteBuffer buildHRRMessage(ClientHello cliHello, int namedGroup) throws IOException { // Create a ByteBuffer that will be large enough to handle // the HelloRetryRequest
ByteBuffer hrrBuf = ByteBuffer.allocate(2048); // More than enough!
// Advance past the TLS record and handshake message headers. We will // go back later and scribble in the proper lengths. The record header // is 5 bytes long, the handshake header is 4.
hrrBuf.position(9);
hrrBuf.putShort((short)TLS_LEGACY_VER);
hrrBuf.put(HRR_RANDOM);
hrrBuf.put((byte)cliHello.sessId.length);
hrrBuf.put(cliHello.sessId);
hrrBuf.putShort(cliHello.cipherSuites.get(0).shortValue());
hrrBuf.put((byte)COMP_NONE);
// Use a separate stream for creating the extension section
ByteArrayOutputStream extBaos = new ByteArrayOutputStream();
DataOutputStream extStream = new DataOutputStream(extBaos);
// Supported version
extStream.writeShort(HELLO_EXT_SUPP_VERS);
extStream.writeShort(2);
extStream.writeShort(TLS_PROT_VER_13);
// Now add in the extensions into the main message
hrrBuf.putShort((short)extStream.size());
hrrBuf.put(extBaos.toByteArray());
// At this point we can go back and write in the TLS record and // handshake message headers.
hrrBuf.flip();
// Write in the TLS record header
hrrBuf.put((byte)TLS_REC_HANDSHAKE);
hrrBuf.putShort((short)TLS_LEGACY_VER);
hrrBuf.putShort((short)(hrrBuf.limit() - 5));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.