Path: blob/master/test/micro/org/openjdk/bench/java/security/SSLHandshake.java
66646 views
/*1* Copyright (c) 2022, 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*/2223package org.openjdk.bench.java.security;2425import org.openjdk.jmh.annotations.Benchmark;26import org.openjdk.jmh.annotations.BenchmarkMode;27import org.openjdk.jmh.annotations.Fork;28import org.openjdk.jmh.annotations.Level;29import org.openjdk.jmh.annotations.Measurement;30import org.openjdk.jmh.annotations.Mode;31import org.openjdk.jmh.annotations.OutputTimeUnit;32import org.openjdk.jmh.annotations.Param;33import org.openjdk.jmh.annotations.Scope;34import org.openjdk.jmh.annotations.Setup;35import org.openjdk.jmh.annotations.State;36import org.openjdk.jmh.annotations.TearDown;37import org.openjdk.jmh.annotations.Warmup;3839import java.nio.ByteBuffer;40import java.security.KeyStore;41import java.util.concurrent.TimeUnit;42import javax.net.ssl.KeyManagerFactory;43import javax.net.ssl.SSLContext;44import javax.net.ssl.SSLEngine;45import javax.net.ssl.SSLEngineResult;46import javax.net.ssl.SSLEngineResult.HandshakeStatus;47import javax.net.ssl.SSLSession;48import javax.net.ssl.TrustManagerFactory;4950@BenchmarkMode(Mode.Throughput)51@OutputTimeUnit(TimeUnit.SECONDS)52@State(Scope.Benchmark)53public class SSLHandshake {5455private SSLContext sslc;5657private SSLEngine clientEngine;58private ByteBuffer clientOut = ByteBuffer.allocate(5);59private ByteBuffer clientIn = ByteBuffer.allocate(1 << 15);6061private SSLEngine serverEngine;62private ByteBuffer serverOut = ByteBuffer.allocate(5);63private ByteBuffer serverIn = ByteBuffer.allocate(1 << 15);6465private ByteBuffer cTOs = ByteBuffer.allocateDirect(1 << 16);66private ByteBuffer sTOc = ByteBuffer.allocateDirect(1 << 16);6768@Param({"true", "false"})69boolean resume;7071@Param({"TLSv1.2", "TLS"})72String tlsVersion;7374@Setup(Level.Trial)75public void init() throws Exception {76KeyStore ks = TestCertificates.getKeyStore();77KeyStore ts = TestCertificates.getTrustStore();7879KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");80kmf.init(ks, new char[0]);8182TrustManagerFactory tmf =83TrustManagerFactory.getInstance("SunX509");84tmf.init(ts);8586SSLContext sslCtx = SSLContext.getInstance(tlsVersion);87sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);88sslc = sslCtx;89}9091private HandshakeStatus checkResult(SSLEngine engine, SSLEngineResult result) {9293HandshakeStatus hsStatus = result.getHandshakeStatus();9495if (hsStatus == HandshakeStatus.NEED_TASK) {96Runnable runnable;97while ((runnable = engine.getDelegatedTask()) != null) {98runnable.run();99}100hsStatus = engine.getHandshakeStatus();101}102return hsStatus;103}104105/**106* This benchmark measures the time needed to perform a TLS handshake.107* Data is exchanged using a pair of ByteBuffers.108* The client and the server both operate on the same thread.109*/110@Benchmark111@Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)112@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)113@Fork(3)114public SSLSession doHandshake() throws Exception {115116createSSLEngines();117boolean isCtoS = true;118for (;;) {119HandshakeStatus result;120if (isCtoS) {121result = checkResult(clientEngine,122clientEngine.wrap(clientOut, cTOs)123);124cTOs.flip();125checkResult(serverEngine,126serverEngine.unwrap(cTOs, serverIn)127);128cTOs.compact();129if (result == HandshakeStatus.NEED_UNWRAP) {130isCtoS = false;131} else if (result == HandshakeStatus.FINISHED) {132break;133} else if (result != HandshakeStatus.NEED_WRAP) {134throw new Exception("Unexpected result "+result);135}136} else {137result = checkResult(serverEngine,138serverEngine.wrap(serverOut, sTOc)139);140sTOc.flip();141checkResult(clientEngine,142clientEngine.unwrap(sTOc, clientIn)143);144sTOc.compact();145if (result == HandshakeStatus.NEED_UNWRAP) {146isCtoS = true;147} else if (result == HandshakeStatus.FINISHED) {148break;149} else if (result != HandshakeStatus.NEED_WRAP) {150throw new Exception("Unexpected result "+result);151}152}153}154155SSLSession session = clientEngine.getSession();156if (resume) {157// TLS 1.3 needs another wrap/unwrap to deliver a session ticket158serverEngine.wrap(serverOut, sTOc);159sTOc.flip();160clientEngine.unwrap(sTOc, clientIn);161sTOc.compact();162} else {163// invalidate TLS1.2 session. TLS 1.3 doesn't care164session.invalidate();165}166return session;167}168169private void createSSLEngines() {170/*171* Configure the serverEngine to act as a server in the SSL/TLS172* handshake.173*/174serverEngine = sslc.createSSLEngine();175serverEngine.setUseClientMode(false);176177/*178* Similar to above, but using client mode instead.179*/180clientEngine = sslc.createSSLEngine("client", 80);181clientEngine.setUseClientMode(true);182}183}184185186