From 19f295b11ce1693126be539b7e3c4d29b7270d29 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Wed, 3 Jun 2026 08:50:33 -0400 Subject: [PATCH] Initial revision. --- .../jdk/internal/event/EventHelper.java | 7 ++- .../jdk/internal/event/TLSHandshakeEvent.java | 3 +- .../classes/sun/security/ssl/Finished.java | 22 ++++++-- .../jdk/jfr/events/TLSHandshakeEvent.java | 5 +- .../event/security/TestTLSHandshakeEvent.java | 55 ++++++++++++++----- .../security/logging/TestTLSHandshakeLog.java | 22 ++++++-- .../test/lib/security/TestTLSHandshake.java | 21 +++++-- 7 files changed, 100 insertions(+), 35 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/event/EventHelper.java b/src/java.base/share/classes/jdk/internal/event/EventHelper.java index 4da2d5854cb18..2ad233e624f31 100644 --- a/src/java.base/share/classes/jdk/internal/event/EventHelper.java +++ b/src/java.base/share/classes/jdk/internal/event/EventHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, 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 @@ -67,12 +67,13 @@ public static void logTLSHandshakeEvent(Instant start, int peerPort, String cipherSuite, String protocolVersion, + String namedGroup, long peerCertId) { assert securityLogger != null; String prepend = getDurationString(start); securityLogger.log(LOG_LEVEL, prepend + - " TLSHandshake: {0}:{1,number,#}, {2}, {3}, {4,number,#}", - peerHost, peerPort, protocolVersion, cipherSuite, peerCertId); + " TLSHandshake: {0}:{1,number,#}, {2}, {3}, {4}, {5,number,#}", + peerHost, peerPort, protocolVersion, cipherSuite, namedGroup, peerCertId); } public static void logSecurityPropertyEvent(String key, diff --git a/src/java.base/share/classes/jdk/internal/event/TLSHandshakeEvent.java b/src/java.base/share/classes/jdk/internal/event/TLSHandshakeEvent.java index f763a0e4d2951..11a35dc188cc3 100644 --- a/src/java.base/share/classes/jdk/internal/event/TLSHandshakeEvent.java +++ b/src/java.base/share/classes/jdk/internal/event/TLSHandshakeEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, 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 @@ -35,4 +35,5 @@ public final class TLSHandshakeEvent extends Event { public String protocolVersion; public String cipherSuite; public long certificateId; + public String namedGroup; } diff --git a/src/java.base/share/classes/sun/security/ssl/Finished.java b/src/java.base/share/classes/sun/security/ssl/Finished.java index bf2d2230719ef..7ca9f50be9714 100644 --- a/src/java.base/share/classes/sun/security/ssl/Finished.java +++ b/src/java.base/share/classes/sun/security/ssl/Finished.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, 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 @@ -562,7 +562,7 @@ private void onConsumeFinished(ClientHandshakeContext chc, // handshake context cleanup. chc.handshakeFinished = true; - recordEvent(chc.conContext.conSession); + recordEvent(chc); // May need to retransmit the last flight for DTLS. if (!chc.sslContext.isDTLS()) { @@ -623,7 +623,7 @@ private void onConsumeFinished(ServerHandshakeContext shc, // handshake context cleanup. shc.handshakeFinished = true; - recordEvent(shc.conContext.conSession); + recordEvent(shc); // May need to retransmit the last flight for DTLS. if (!shc.sslContext.isDTLS()) { @@ -765,7 +765,7 @@ private byte[] onProduceFinished(ClientHandshakeContext chc, // handshake context cleanup. chc.handshakeFinished = true; chc.conContext.finishHandshake(); - recordEvent(chc.conContext.conSession); + recordEvent(chc); // The handshake message has been delivered. @@ -1164,7 +1164,7 @@ private void onConsumeFinished(ServerHandshakeContext shc, if (!shc.sslContext.isDTLS()) { shc.conContext.finishHandshake(); } - recordEvent(shc.conContext.conSession); + recordEvent(shc); // // produce @@ -1174,9 +1174,10 @@ private void onConsumeFinished(ServerHandshakeContext shc, } } - private static void recordEvent(SSLSessionImpl session) { + private static void recordEvent(HandshakeContext hc) { TLSHandshakeEvent event = new TLSHandshakeEvent(); if (event.shouldCommit() || EventHelper.isLoggingSecurity()) { + SSLSessionImpl session = hc.conContext.conSession; int hash = 0; try { // use hash code for Id @@ -1187,12 +1188,20 @@ private static void recordEvent(SSLSessionImpl session) { // not verified msg } long peerCertificateId = Integer.toUnsignedLong(hash); + String namedGroup = "N/A"; + for (SSLCredentials cred : hc.handshakeCredentials) { + if (cred instanceof NamedGroupCredentials ngCred) { + namedGroup = ngCred.getNamedGroup().name; + break; + } + } if (event.shouldCommit()) { event.peerHost = session.getPeerHost(); event.peerPort = session.getPeerPort(); event.cipherSuite = session.getCipherSuite(); event.protocolVersion = session.getProtocol(); event.certificateId = peerCertificateId; + event.namedGroup = namedGroup; event.commit(); } if (EventHelper.isLoggingSecurity()) { @@ -1201,6 +1210,7 @@ private static void recordEvent(SSLSessionImpl session) { session.getPeerPort(), session.getCipherSuite(), session.getProtocol(), + namedGroup, peerCertificateId); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java index d0d81ac63bc39..b1efa748ca1ad 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, 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 @@ -57,4 +57,7 @@ public final class TLSHandshakeEvent extends MirrorEvent { @CertificateId @Unsigned public long certificateId; + + @Label("Named Group") + public String namedGroup; } diff --git a/test/jdk/jdk/jfr/event/security/TestTLSHandshakeEvent.java b/test/jdk/jdk/jfr/event/security/TestTLSHandshakeEvent.java index 559290f50b47f..35bdf4d149201 100644 --- a/test/jdk/jdk/jfr/event/security/TestTLSHandshakeEvent.java +++ b/test/jdk/jdk/jfr/event/security/TestTLSHandshakeEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, 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 @@ -30,10 +30,11 @@ import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; import jdk.test.lib.security.TestTLSHandshake; +import jdk.test.lib.security.SecurityUtils; /* * @test - * @bug 8148188 + * @bug 8148188 8301626 * @summary Enhance the security libraries to record events of interest * @requires vm.flagless * @requires vm.hasJFR @@ -41,28 +42,54 @@ * @run main/othervm jdk.jfr.event.security.TestTLSHandshakeEvent */ public class TestTLSHandshakeEvent { + record TLSConfig(String protocol, String cipherSuite, String namedGroup, + long certId) {}; + + private static final List CONFIGS = List.of( + new TLSConfig("TLSv1.3", "TLS_AES_256_GCM_SHA384", "X25519MLKEM768", + 3237675498l), + new TLSConfig("TLSv1.3", "TLS_CHACHA20_POLY1305_SHA256", + "X25519MLKEM768", 3237675498l), + new TLSConfig("TLSv1.2", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "secp256r1", 3237675498l), + new TLSConfig("TLSv1.2", "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", + "ffdhe2048", 3188175476l), + new TLSConfig("TLSv1.2", "TLS_RSA_WITH_AES_256_CBC_SHA", + "N/A", 3010289526l) + ); + public static void main(String[] args) throws Exception { - try (Recording recording = new Recording()) { - recording.enable(EventNames.TLSHandshake).withStackTrace(); - recording.start(); - TestTLSHandshake handshake = new TestTLSHandshake(); - handshake.run(); - recording.stop(); + // re-enable TLS_RSA suites as one test depends on it + SecurityUtils.removeFromDisabledTlsAlgs("TLS_RSA_*"); + for (TLSConfig config : CONFIGS) { + System.out.println(config); + try (Recording recording = new Recording()) { + recording.enable(EventNames.TLSHandshake).withStackTrace(); + recording.start(); + TestTLSHandshake handshake = new TestTLSHandshake(); + handshake.protocolVersion = config.protocol(); + handshake.cipherSuite = config.cipherSuite(); + handshake.namedGroup = config.namedGroup(); + handshake.run(); + recording.stop(); - List events = Events.fromRecording(recording); - Events.hasEvents(events); - assertEvent(events, handshake); + List events = Events.fromRecording(recording); + Events.hasEvents(events); + assertEvent(events, handshake, config); + } } } - private static void assertEvent(List events, TestTLSHandshake handshake) throws Exception { + private static void assertEvent(List events, + TestTLSHandshake handshake, TLSConfig config) throws Exception { System.out.println(events); for (RecordedEvent e : events) { if (handshake.peerHost.equals(e.getString("peerHost"))) { Events.assertField(e, "peerPort").equal(handshake.peerPort); Events.assertField(e, "protocolVersion").equal(handshake.protocolVersion); - Events.assertField(e, "certificateId").equal(TestTLSHandshake.CERT_ID); - Events.assertField(e, "cipherSuite").equal(TestTLSHandshake.CIPHER_SUITE); + Events.assertField(e, "certificateId").equal(config.certId()); + Events.assertField(e, "cipherSuite").equal(handshake.cipherSuite); + Events.assertField(e, "namedGroup").equal(handshake.namedGroup); var method = e.getStackTrace().getFrames().get(0).getMethod(); if (method.getName().equals("recordEvent")) { throw new Exception("Didn't expected recordEvent as top frame"); diff --git a/test/jdk/jdk/security/logging/TestTLSHandshakeLog.java b/test/jdk/jdk/security/logging/TestTLSHandshakeLog.java index db34fb113d669..8986bf335a6fc 100644 --- a/test/jdk/jdk/security/logging/TestTLSHandshakeLog.java +++ b/test/jdk/jdk/security/logging/TestTLSHandshakeLog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, 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 @@ -27,13 +27,20 @@ /* * @test - * @bug 8148188 + * @bug 8148188 8301626 * @summary Enhance the security libraries to record events of interest * @library /test/lib /test/jdk * @run main/othervm jdk.security.logging.TestTLSHandshakeLog LOGGING_ENABLED * @run main/othervm jdk.security.logging.TestTLSHandshakeLog LOGGING_DISABLED */ public class TestTLSHandshakeLog { + record TLSConfig(String protocol, String cipherSuite, String namedGroup) {}; + + private static TLSConfig CONFIG = + new TLSConfig("TLSv1.2", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "secp256r1"); + public static void main(String[] args) throws Exception { LogJvm l = new LogJvm(TLSHandshake.class, args); l.addExpected("FINE: X509Certificate: Alg:SHA256withRSA, Serial:" + TestTLSHandshake.CERT_SERIAL); @@ -44,15 +51,20 @@ public static void main(String[] args) throws Exception { ", " + TestTLSHandshake.CERT_ID); l.addExpected("SunJSSE Test Serivce"); l.addExpected("TLSHandshake:"); - l.addExpected("TLSv1.2"); - l.addExpected(TestTLSHandshake.CIPHER_SUITE +", " + TestTLSHandshake.CERT_ID); + l.addExpected(CONFIG.protocol()); + l.addExpected(CONFIG.cipherSuite()); + l.addExpected(CONFIG.namedGroup()); + l.addExpected(Long.toString(TestTLSHandshake.CERT_ID)); l.testExpected(); } public static class TLSHandshake { public static void main(String[] args) throws Exception { TestTLSHandshake handshake = new TestTLSHandshake(); + handshake.protocolVersion = CONFIG.protocol(); + handshake.cipherSuite = CONFIG.cipherSuite(); + handshake.namedGroup = CONFIG.namedGroup(); handshake.run(); } } -} \ No newline at end of file +} diff --git a/test/lib/jdk/test/lib/security/TestTLSHandshake.java b/test/lib/jdk/test/lib/security/TestTLSHandshake.java index 1b36f66f7e0c6..30224ac9d74aa 100644 --- a/test/lib/jdk/test/lib/security/TestTLSHandshake.java +++ b/test/lib/jdk/test/lib/security/TestTLSHandshake.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, 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 @@ -25,14 +25,12 @@ import java.io.*; +import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; - public final class TestTLSHandshake extends SSLSocketTest { - public static final String CIPHER_SUITE = - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; public static final long CERT_ID = Integer.toUnsignedLong(-1057291798); public static final long ANCHOR_CERT_ID = Integer.toUnsignedLong(1688661792); public static final String CERT_SERIAL = "00:ed:be:c8:f7:05:af:25:14"; @@ -41,6 +39,8 @@ public final class TestTLSHandshake extends SSLSocketTest { public String protocolVersion; public String peerHost; public int peerPort; + public String cipherSuite; + public String namedGroup; @Override protected void runServerApplication(SSLSocket socket) throws Exception { @@ -54,7 +54,17 @@ protected void runServerApplication(SSLSocket socket) throws Exception { @Override protected void runClientApplication(SSLSocket socket) throws Exception { - socket.setEnabledCipherSuites(new String[] { CIPHER_SUITE }); + SSLParameters params = socket.getSSLParameters(); + if (protocolVersion != null) { + params.setProtocols(new String [] { protocolVersion }); + } + if (cipherSuite != null) { + params.setCipherSuites(new String[] { cipherSuite }); + } + if (namedGroup != null) { + params.setNamedGroups(new String[] { namedGroup }); + } + socket.setSSLParameters(params); InputStream sslIS = socket.getInputStream(); OutputStream sslOS = socket.getOutputStream(); @@ -66,5 +76,6 @@ protected void runClientApplication(SSLSocket socket) throws Exception { protocolVersion = sslSession.getProtocol(); peerHost = sslSession.getPeerHost(); peerPort = sslSession.getPeerPort(); + cipherSuite = sslSession.getCipherSuite(); } }