--- old/src/java.base/share/classes/java/security/Security.java 2018-11-06 08:40:49.955364584 +0000 +++ new/src/java.base/share/classes/java/security/Security.java 2018-11-06 08:40:49.171364584 +0000 @@ -30,6 +30,8 @@ import java.io.*; import java.net.URL; +import jdk.internal.event.EventHelper; +import jdk.internal.event.JdkSecurityPropertyModificationEvent; import jdk.internal.misc.SharedSecrets; import jdk.internal.util.StaticProperty; import sun.security.util.Debug; @@ -795,6 +797,40 @@ check("setProperty."+key); props.put(key, datum); invalidateSMCache(key); /* See below. */ + + if (isJdkSecurityProperty(key)) { + JdkSecurityPropertyModificationEvent spe = new JdkSecurityPropertyModificationEvent(); + // following is a no-op if event is disabled + spe.key = key; + spe.value = datum; + spe.commit(); + + if (EventHelper.isLoggingSecurity()) { + EventHelper.logJdkSecurityPropertyEvent(key, datum); + } + } + } + + /* + * Helper method to identify security properties + * that should be specific to JDK usage. + */ + private static boolean isJdkSecurityProperty(String key) { + return key.startsWith("com.sun.") || + key.startsWith("crypto.policy") || + key.startsWith("jceks.key.serialFilter") || + key.startsWith("jdk.") || + key.startsWith("keystore.type") || + key.startsWith("krb5.kdc.bad.policy") || + key.startsWith("login.config") || + key.startsWith("networkaddress.cache.") || + key.startsWith("ocsp.") || + key.startsWith("package.") || + key.startsWith("policy.") || + key.startsWith("securerandom.") || + key.startsWith("security.") || + key.startsWith("ssl.") || + key.startsWith("sun.rmi."); } /* --- old/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java 2018-11-06 08:40:51.235364584 +0000 +++ new/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java 2018-11-06 08:40:50.763364584 +0000 @@ -29,7 +29,13 @@ import java.security.InvalidAlgorithmParameterException; import java.security.cert.*; import java.util.*; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import jdk.internal.event.X509ValidationEvent; +import jdk.internal.event.EventHelper; import sun.security.provider.certpath.PKIX.ValidatorParams; import sun.security.validator.Validator; import sun.security.x509.X509CertImpl; @@ -47,6 +53,7 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi { private static final Debug debug = Debug.getInstance("certpath"); + private static final AtomicLong validationEventNumber = new AtomicLong(); /** * Default constructor. @@ -234,7 +241,33 @@ params.certificates(), certPathCheckers); + X509ValidationEvent xve = new X509ValidationEvent(); + if(xve.shouldCommit() || EventHelper.isLoggingSecurity()) { + int[] hashCodes = params.certificates().stream() + .mapToInt(x -> x.hashCode()) + .toArray(); + int anchorHashId = + anchor.getTrustedCert().hashCode(); + if (xve.shouldCommit()) { + xve.hashCode = anchorHashId; + int certificatePos = 1; //anchor cert + xve.certificatePosition = certificatePos; + xve.validationId = validationEventNumber.incrementAndGet(); + xve.commit(); + // now, iterate through remaining + for (int hashCode : hashCodes) { + xve.hashCode = hashCode; + xve.certificatePosition = ++certificatePos; + xve.commit(); + + } + } + if (EventHelper.isLoggingSecurity()) { + EventHelper.logX509ValidationEvent(anchorHashId, hashCodes); + } + } return new PKIXCertPathValidatorResult(anchor, pc.getPolicyTree(), bc.getPublicKey()); } + } --- old/src/java.base/share/classes/sun/security/ssl/Finished.java 2018-11-06 08:40:52.331364584 +0000 +++ new/src/java.base/share/classes/sun/security/ssl/Finished.java 2018-11-06 08:40:51.867364584 +0000 @@ -40,6 +40,10 @@ import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import javax.net.ssl.SSLPeerUnverifiedException; + +import jdk.internal.event.EventHelper; +import jdk.internal.event.TLSHandshakeEvent; import sun.security.internal.spec.TlsPrfParameterSpec; import sun.security.ssl.CipherSuite.HashAlg; import static sun.security.ssl.CipherSuite.HashAlg.H_NONE; @@ -548,6 +552,7 @@ // handshake context cleanup. chc.handshakeFinished = true; + recordEvent(chc.conContext.conSession); // May need to retransmit the last flight for DTLS. if (!chc.sslContext.isDTLS()) { @@ -597,6 +602,7 @@ // handshake context cleanup. shc.handshakeFinished = true; + recordEvent(shc.conContext.conSession); // May need to retransmit the last flight for DTLS. if (!shc.sslContext.isDTLS()) { @@ -730,6 +736,8 @@ // handshake context cleanup. chc.handshakeFinished = true; chc.conContext.finishHandshake(); + recordEvent(chc.conContext.conSession); + // The handshake message has been delivered. return null; @@ -1063,6 +1071,7 @@ if (!shc.sslContext.isDTLS()) { shc.conContext.finishHandshake(); } + recordEvent(shc.conContext.conSession); // // produce @@ -1074,4 +1083,34 @@ } } + + private static void recordEvent(SSLSessionImpl session) { + TLSHandshakeEvent event = new TLSHandshakeEvent(); + if (event.shouldCommit() || EventHelper.isLoggingSecurity()) { + int peerHashCode = 0; + try { + peerHashCode = session + .getCertificateChain()[0] + .hashCode(); + } catch (SSLPeerUnverifiedException e) { + // not verified msg +} + if(event.shouldCommit()) { + event.peerHost = session.getPeerHost(); + event.peerPort = session.getPeerPort(); + event.cipherSuite = session.getCipherSuite(); + event.protocolVersion = session.getProtocol(); + event.peerHashCode = peerHashCode; + event.commit(); + } + if (EventHelper.isLoggingSecurity()) { + EventHelper.logTLSHandshakeEvent(null, + session.getPeerHost(), + session.getPeerPort(), + session.getCipherSuite(), + session.getProtocol(), + peerHashCode); + } + } + } } --- old/src/java.base/share/classes/sun/security/x509/X509CertImpl.java 2018-11-06 08:40:53.299364584 +0000 +++ new/src/java.base/share/classes/sun/security/x509/X509CertImpl.java 2018-11-06 08:40:52.855364584 +0000 @@ -42,7 +42,8 @@ import javax.security.auth.x500.X500Principal; -import java.util.Base64; +import jdk.internal.event.EventHelper; +import jdk.internal.event.X509CertificateEvent; import sun.security.util.*; import sun.security.provider.X509Factory; @@ -154,6 +155,9 @@ // AuthorityInformationAccess cache private Set authInfoAccess; + // Event recording cache list + private List recordedCerts; + /** * PublicKey that has previously been used to verify * the signature of this certificate. Null if the certificate has not @@ -1861,6 +1865,8 @@ if (! algId.equals(infoSigAlg)) throw new CertificateException("Signature algorithm mismatch"); readOnly = true; + // record if configured to + commitEvent(); } /** @@ -2017,4 +2023,57 @@ buf.append(hexChars[high]) .append(hexChars[low]); } + + private void commitEvent() { + X509CertificateEvent xce = new X509CertificateEvent(); + if (xce.shouldCommit() || EventHelper.isLoggingSecurity()) { + if (recordedCerts == null) { + recordedCerts = new ArrayList<>(); + } + int hash = hashCode(); + if (!recordedCerts.contains(hash)) { + recordedCerts.add(hash); + try { + PublicKey pKey = info.pubKey.get(CertificateX509Key.KEY); + String algId = + info.algId.get(CertificateAlgorithmId.ALGORITHM).getName(); + String serNum = getSerialNumber().toString(16); + String subject = info.subject.getName(); + String issuer = info.issuer.getName(); + String keyType = pKey.getAlgorithm(); + int hashCode = hashCode(); + int length = KeyUtil.getKeySize(pKey); + long beginDate = + info.interval.get(CertificateValidity.NOT_BEFORE).getTime(); + long endDate = + info.interval.get(CertificateValidity.NOT_AFTER).getTime(); + if (xce.shouldCommit()) { + xce.algorithm = algId; + xce.serialNumber = serNum; + xce.subject = subject; + xce.issuer = issuer; + xce.keyType = keyType; + xce.keyLength = length; + xce.hashCode = hashCode; + xce.validFrom = beginDate; + xce.validUntil = endDate; + xce.commit(); + } + if (EventHelper.isLoggingSecurity()) { + EventHelper.logX509CertificateEvent(algId, + serNum, + subject, + issuer, + keyType, + length, + hashCode, + beginDate, + endDate); + } + } catch (IOException e) { + // ignore for recording purposes + } + } + } + } } --- old/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java 2018-11-06 08:40:54.343364584 +0000 +++ new/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java 2018-11-06 08:40:53.843364584 +0000 @@ -39,8 +39,12 @@ import jdk.jfr.events.FileForceEvent; import jdk.jfr.events.FileReadEvent; import jdk.jfr.events.FileWriteEvent; +import jdk.jfr.events.JdkSecurityPropertyModificationEvent; import jdk.jfr.events.SocketReadEvent; import jdk.jfr.events.SocketWriteEvent; +import jdk.jfr.events.TLSHandshakeEvent; +import jdk.jfr.events.X509CertificateEvent; +import jdk.jfr.events.X509ValidationEvent; import jdk.jfr.internal.JVM; import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; @@ -52,6 +56,10 @@ public final class JDKEvents { private static final Class[] mirrorEventClasses = { + JdkSecurityPropertyModificationEvent.class, + TLSHandshakeEvent.class, + X509CertificateEvent.class, + X509ValidationEvent.class }; private static final Class[] eventClasses = { @@ -64,7 +72,11 @@ ExceptionStatisticsEvent.class, ErrorThrownEvent.class, ActiveSettingEvent.class, - ActiveRecordingEvent.class + ActiveRecordingEvent.class, + jdk.internal.event.JdkSecurityPropertyModificationEvent.class, + jdk.internal.event.TLSHandshakeEvent.class, + jdk.internal.event.X509CertificateEvent.class, + jdk.internal.event.X509ValidationEvent.class }; // This is a list of the classes with instrumentation code that should be applied. --- old/src/jdk.jfr/share/conf/jfr/default.jfc 2018-11-06 08:40:55.195364584 +0000 +++ new/src/jdk.jfr/share/conf/jfr/default.jfc 2018-11-06 08:40:54.715364584 +0000 @@ -593,6 +593,26 @@ 20 ms + + false + true + + + + false + true + + + + false + true + + + + false + true + + false true --- old/src/jdk.jfr/share/conf/jfr/profile.jfc 2018-11-06 08:40:56.399364584 +0000 +++ new/src/jdk.jfr/share/conf/jfr/profile.jfc 2018-11-06 08:40:55.859364584 +0000 @@ -593,6 +593,26 @@ 10 ms + + false + true + + + + false + true + + + + false + true + + + + false + true + + false true --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/java.base/share/classes/jdk/internal/event/EventHelper.java 2018-11-06 08:40:57.063364584 +0000 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.internal.event; + +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * A helper class to have events logged to a JDK Event Logger + */ + +public final class EventHelper { + + private static final System.Logger.Level LOG_LEVEL = System.Logger.Level.DEBUG; + + // helper class used for logging security related events for now + private static final String SECURITY_LOGGER_NAME = "jdk.event.security"; + private static final System.Logger SECURITY_LOGGER = + System.getLogger(SECURITY_LOGGER_NAME); + private static final boolean LOGGING_SECURITY = + SECURITY_LOGGER.isLoggable(LOG_LEVEL); + + public static void logTLSHandshakeEvent(Instant start, + String peerHost, + int peerPort, + String cipherSuite, + String protocolVersion, + int peerHashCode) { + String prepend = getDurationString(start); + SECURITY_LOGGER.log(LOG_LEVEL, prepend + + " TLSHandshake: {0}:{1,number,#}, {2}, {3}, {4,number,#}", + peerHost, peerPort, protocolVersion, cipherSuite, peerHashCode); + } + + public static void logJdkSecurityPropertyEvent(String key, + String value) { + + if (isLoggingSecurity()) { + SECURITY_LOGGER.log(LOG_LEVEL, + "JdkSecurityPropertyModification: key:{0}, value:{1}", key, value); + } + } + + public static void logX509ValidationEvent(int anchorHash, + int[] hashCodes) { + String codes = IntStream.of(hashCodes) + .mapToObj(Integer::toString) + .collect(Collectors.joining(", ")); + SECURITY_LOGGER.log(LOG_LEVEL, + "ValidationChain: {0,number,#}, {1}", anchorHash, codes); + } + + public static void logX509CertificateEvent(String algId, + String serialNum, + String subject, + String issuer, + String keyType, + int length, + int hashCode, + long beginDate, + long endDate) { + SECURITY_LOGGER.log(LOG_LEVEL, "X509Certificate: Alg:{0}, Serial:{1}" + + ", Subject:{2}, Issuer:{3}, Key type:{4}, Length:{5,number,#}" + + ", Hash code:{6,number,#}, Valid from:{7}, Valid until:{8}", + algId, serialNum, subject, issuer, keyType, length, + hashCode, new Date(beginDate), new Date(endDate)); + } + + /** + * Method to calculate a duration timestamp for events which measure + * the start and end times of certain operations. + * @param start Instant indicating when event started recording + * @return A string representing duraction from start time to + * time of this method call. Empty string is start is null. + */ + private static String getDurationString(Instant start) { + if (start != null) { + Duration duration = Duration.between(start, Instant.now()); + long micros = duration.toNanos() / 1_000; + if (micros < 1_000_000) { + return "duration = " + (micros / 1_000.0) + " ms:"; + } else { + return "duration = " + ((micros / 1_000) / 1_000.0) + " s:"; + } + } else { + return ""; + } + } + + /** + * Helper to determine if security events are being logged + * at a preconfigured logging level. The configuration value + * is read once at class initialization. + * + * @return boolean indicating whether an event should be logged + */ + public static boolean isLoggingSecurity() { + return LOGGING_SECURITY; + } +} \ No newline at end of file --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/java.base/share/classes/jdk/internal/event/JdkSecurityPropertyModificationEvent.java 2018-11-06 08:40:58.099364584 +0000 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.internal.event; + +/** + * Event details relating to the modification of a JDK Security property. + */ + +public final class JdkSecurityPropertyModificationEvent extends Event { + public String key; + public String value; +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/java.base/share/classes/jdk/internal/event/TLSHandshakeEvent.java 2018-11-06 08:40:59.055364584 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.internal.event; + +/** + * Event recording details of successful TLS handshakes. + */ + +public final class TLSHandshakeEvent extends Event { + public String peerHost; + public int peerPort; + public String protocolVersion; + public String cipherSuite; + public int peerHashCode; + +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/java.base/share/classes/jdk/internal/event/X509CertificateEvent.java 2018-11-06 08:40:59.907364584 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.internal.event; + + +/** + * Event recording details of X.509 Certificate. + */ + +public final class X509CertificateEvent extends Event { + public String algorithm; + public String serialNumber; + public String subject; + public String issuer; + public String keyType; + public int keyLength; + public int hashCode; + public long validFrom; + public long validUntil; +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/java.base/share/classes/jdk/internal/event/X509ValidationEvent.java 2018-11-06 08:41:00.883364584 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.internal.event; + +/** + * Event recording details of X.509 Certificate serial numbers + * used in X509 cert path validation + */ + +public final class X509ValidationEvent extends Event { + public int hashCode; + public int certificatePosition; + public long validationId; +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/jdk.jfr/share/classes/jdk/jfr/events/CertificateHashCode.java 2018-11-06 08:41:01.855364584 +0000 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.jfr.events; + +import jdk.jfr.Label; +import jdk.jfr.Relational; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Label("X509 Certificate Hash Code") +@Relational +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface CertificateHashCode { +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/jdk.jfr/share/classes/jdk/jfr/events/JdkSecurityPropertyModificationEvent.java 2018-11-06 08:41:03.011364584 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.jfr.events; + +import jdk.jfr.*; +import jdk.jfr.internal.MirrorEvent; + +@Category({"Java Development Kit", "Security"}) +@Label("Security Property Modification") +@Name("jdk.JdkSecurityPropertyModification") +@Description("Modification of JDK Security property") +@MirrorEvent(className = "jdk.internal.event.JdkSecurityPropertyModificationEvent") +public final class JdkSecurityPropertyModificationEvent extends AbstractJDKEvent { + @Label("Key") + public String key; + + @Label("Value") + public String value; +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java 2018-11-06 08:41:03.959364584 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.jfr.events; + +import jdk.jfr.Category; +import jdk.jfr.Description; +import jdk.jfr.Label; +import jdk.jfr.Name; +import jdk.jfr.internal.MirrorEvent; + +@Category({"Java Development Kit", "Security"}) +@Label("TLS Handshake") +@Name("jdk.TLSHandshake") +@Description("Parameters used in TLS Handshake") +@MirrorEvent(className = "jdk.internal.event.TLSHandshakeEvent") +public final class TLSHandshakeEvent extends AbstractJDKEvent { + @Label("Peer Host") + public String peerHost; + + @Label("Peer Port") + public int peerPort; + + @Label("Protocol Version") + public String protocolVersion; + + @Label("Cipher Suite") + public String cipherSuite; + + @Label("Peer Certificate Hash Code") + @CertificateHashCode + public int peerHashCode; +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/jdk.jfr/share/classes/jdk/jfr/events/X509CertificateEvent.java 2018-11-06 08:41:04.815364584 +0000 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.jfr.events; + +import jdk.jfr.*; +import jdk.jfr.internal.MirrorEvent; + +@Category({"Java Development Kit", "Security"}) +@Label("X509 Certificate") +@Name("jdk.X509Certificate") +@Description("Details of X.509 Certificate parsed by JDK") +@MirrorEvent(className = "jdk.internal.event.X509CertificateEvent") +public final class X509CertificateEvent extends AbstractJDKEvent { + @Label("Signature Algorithm") + public String algorithm; + + @Label("Serial Number") + public String serialNumber; + + @Label("Subject") + public String subject; + + @Label("Issuer") + public String issuer; + + @Label("Key Type") + public String keyType; + + @Label("Key Length") + public int keyLength; + + @Label("Hash Code") + @CertificateHashCode + public int hashCode; + + @Label("Valid From") + @Timestamp(Timestamp.MILLISECONDS_SINCE_EPOCH) + public long validFrom; + + @Label("Valid Until") + @Timestamp(Timestamp.MILLISECONDS_SINCE_EPOCH) + public long validUntil; +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/src/jdk.jfr/share/classes/jdk/jfr/events/X509ValidationEvent.java 2018-11-06 08:41:05.703364584 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.jfr.events; + +import jdk.jfr.*; +import jdk.jfr.internal.MirrorEvent; + +@Category({"Java Development Kit", "Security"}) +@Label("X509 Validation") +@Name("jdk.X509Validation") +@Description("Serial numbers from X.509 Certificates forming chain of trust") +@MirrorEvent(className = "jdk.internal.event.X509ValidationEvent") +public final class X509ValidationEvent extends AbstractJDKEvent { + @CertificateHashCode + @Label("Certificate Hash Code") + public int hashCode; + + @Label("Certificate Position") + @Description("Certificate position in chain of trust, 1 = trust anchor") + public int certificatePosition; + + @Label("Validation Id") + public long validationId; + +} --- old/test/jdk/jdk/jfr/event/metadata/TestDefaultConfigurations.java 2018-11-06 08:41:07.187364584 +0000 +++ new/test/jdk/jdk/jfr/event/metadata/TestDefaultConfigurations.java 2018-11-06 08:41:06.575364584 +0000 @@ -173,6 +173,10 @@ insertSetting(doc, EventNames.ActiveRecording, "threshold", "0 ns"); insertSetting(doc, EventNames.JavaExceptionThrow, "threshold", "0 ns"); insertSetting(doc, EventNames.JavaErrorThrow, "threshold", "0 ns"); + insertSetting(doc, EventNames.JdkSecurityProperty, "threshold", "0 ns"); + insertSetting(doc, EventNames.TLSHandshake, "threshold", "0 ns"); + insertSetting(doc, EventNames.X509Certificate, "threshold", "0 ns"); + insertSetting(doc, EventNames.X509Validation, "threshold", "0 ns"); return doc; } --- old/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java 2018-11-06 08:41:08.059364584 +0000 +++ new/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java 2018-11-06 08:41:07.579364584 +0000 @@ -201,6 +201,10 @@ settingValues.put(EventNames.ActiveRecording + "#threshold", "0 ns"); settingValues.put(EventNames.JavaExceptionThrow + "#threshold", "0 ns"); settingValues.put(EventNames.JavaErrorThrow + "#threshold", "0 ns"); + settingValues.put(EventNames.JdkSecurityProperty + "#threshold", "0 ns"); + settingValues.put(EventNames.TLSHandshake + "#threshold", "0 ns"); + settingValues.put(EventNames.X509Certificate + "#threshold", "0 ns"); + settingValues.put(EventNames.X509Validation + "#threshold", "0 ns"); try (Recording recording = new Recording(c)) { Map eventTypes = new HashMap<>(); --- old/test/lib/jdk/test/lib/jfr/EventNames.java 2018-11-06 08:41:09.091364584 +0000 +++ new/test/lib/jdk/test/lib/jfr/EventNames.java 2018-11-06 08:41:08.575364584 +0000 @@ -169,6 +169,10 @@ public final static String JavaErrorThrow = PREFIX + "JavaErrorThrow"; public final static String ModuleRequire = PREFIX + "ModuleRequire"; public final static String ModuleExport = PREFIX + "ModuleExport"; + public final static String TLSHandshake = PREFIX + "TLSHandshake"; + public final static String X509Certificate = PREFIX + "X509Certificate"; + public final static String X509Validation = PREFIX + "X509Validation"; + public final static String JdkSecurityProperty = PREFIX + "JdkSecurityPropertyModification"; // Flight Recorder public final static String DumpReason = PREFIX + "DumpReason"; --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/jfr/event/security/TestJdkSecurityPropertyModificationEvent.java 2018-11-06 08:41:09.611364584 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.jfr.event.security; + +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; +import jdk.test.lib.security.TestJdkSecurityPropertyModification; +import static jdk.test.lib.security.TestJdkSecurityPropertyModification.jdkProps; +import static jdk.test.lib.security.TestJdkSecurityPropertyModification.GOOD_VALUE; + +/* + * @test + * @bug 8148188 + * @summary Enhance the security libraries to record events of interest + * @key jfr + * @library /test/lib + * @run main/othervm jdk.jfr.event.security.TestJdkSecurityPropertyModificationEvent + */ +public class TestJdkSecurityPropertyModificationEvent { + + public static void main(String[] args) throws Exception { + try (Recording recording = new Recording()) { + recording.enable(EventNames.JdkSecurityProperty); + recording.start(); + TestJdkSecurityPropertyModification.runTest(); + recording.stop(); + + List events = Events.fromRecording(recording); + Events.hasEvents(events); + assertEvent(events); + } + } + + private static void assertEvent(List events) throws Exception { + int i = 1; + Asserts.assertEquals(events.size(), jdkProps.size(), + "Incorrect number of events"); + for (RecordedEvent e : events) { + if (jdkProps.contains(e.getString("key"))) { + Events.assertField(e, "value").equal(GOOD_VALUE); + i++; + } else { + System.out.println(events); + throw new Exception("Unexpected event at index:" + i); + } + } + } +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/jfr/event/security/TestTLSHandshakeEvent.java 2018-11-06 08:41:10.527364584 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.jfr.event.security; + +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; +import jdk.test.lib.security.TestTLSHandshake; + +/* + * @test + * @bug 8148188 + * @summary Enhance the security libraries to record events of interest + * @key jfr + * @library /test/lib + * @run main/othervm jdk.jfr.event.security.TestTLSHandshakeEvent + */ +public class TestTLSHandshakeEvent { + public static void main(String[] args) throws Exception { + try (Recording recording = new Recording()) { + recording.enable(EventNames.TLSHandshake); + recording.start(); + TestTLSHandshake handshake = new TestTLSHandshake(); + handshake.run(); + recording.stop(); + + List events = Events.fromRecording(recording); + Events.hasEvents(events); + assertEvent(events, handshake); + } + } + + private static void assertEvent(List events, TestTLSHandshake handshake) 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, "peerHashCode").equal(TestTLSHandshake.HASHCODE); + Events.assertField(e, "cipherSuite").equal(TestTLSHandshake.CIPHER_SUITE); + return; + } + } + System.out.println(events); + throw new Exception("Could not find event with hostname: " + handshake.peerHost); + } +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/jfr/event/security/TestX509CertificateEvent.java 2018-11-06 08:41:11.535364584 +0000 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.jfr.event.security; + +import java.security.cert.CertificateFactory; +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; +import jdk.test.lib.security.TestCertificate; + +/* + * @test + * @bug 8148188 + * @summary Enhance the security libraries to record events of interest + * @key jfr + * @library /test/lib + * @run main/othervm jdk.jfr.event.security.TestX509CertificateEvent + */ +public class TestX509CertificateEvent { + public static void main(String[] args) throws Exception { + try (Recording recording = new Recording()) { + recording.enable(EventNames.X509Certificate); + recording.start(); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + TestCertificate.ONE.generate(cf); + TestCertificate.TWO.generate(cf); + // Generate twice to make sure only one event per certificate is generated + TestCertificate.ONE.generate(cf); + TestCertificate.TWO.generate(cf); + + recording.stop(); + + List events = Events.fromRecording(recording); + Asserts.assertEquals(events.size(), 2, "Incorrect number of X509Certificate events"); + assertEvent(events, TestCertificate.ONE); + assertEvent(events, TestCertificate.TWO); + } + } + + private static void assertEvent(List events, TestCertificate cert) throws Exception { + for (RecordedEvent e : events) { + if (e.getInt("hashCode") == cert.hashCode) { + Events.assertField(e, "algorithm").equal(cert.algorithm); + Events.assertField(e, "subject").equal(cert.subject); + Events.assertField(e, "issuer").equal(cert.issuer); + Events.assertField(e, "keyType").equal(cert.keyType); + Events.assertField(e, "keyLength").equal(cert.keyLength); + Events.assertField(e, "serialNumber").equal(cert.serialNumber); + return; + } + } + System.out.println(events); + throw new Exception("Could not find event with hash code: " + cert.hashCode); + } +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/jfr/event/security/TestX509ValidationEvent.java 2018-11-06 08:41:12.495364584 +0000 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.jfr.event.security; + +import java.util.List; + +import jdk.jfr.AnnotationElement; +import jdk.jfr.EventType; +import jdk.jfr.FlightRecorder; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.Events; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.security.TestCertificate; + +/* + * @test + * @bug 8148188 + * @summary Enhance the security libraries to record events of interest + * @key jfr + * @library /test/lib + * @modules jdk.jfr/jdk.jfr.events + * @run main/othervm jdk.jfr.event.security.TestX509ValidationEvent + */ +public class TestX509ValidationEvent { + public static void main(String[] args) throws Exception { + try (Recording recording = new Recording()) { + recording.enable(EventNames.X509Validation); + recording.start(); + // intermeditate certificate test + TestCertificate.generateChain(false); + recording.stop(); + List events = Events.fromRecording(recording); + Asserts.assertEquals(events.size(), 3, "Incorrect number of events"); + assertEvent1(events); + } + + try (Recording recording = new Recording()) { + recording.enable(EventNames.X509Validation); + recording.start(); + // self signed certificate test + TestCertificate.generateChain(true); + recording.stop(); + List events = Events.fromRecording(recording); + Asserts.assertEquals(events.size(), 2, "Incorrect number of events"); + assertEvent2(events); + } + } + + private static void assertEvent1(List events) throws Exception { + for (RecordedEvent e : events) { + int pos = e.getInt("certificatePosition"); + switch (pos) { + case 1: + Events.assertField(e, "hashCode") + .equal(TestCertificate.ROOT_CA.hashCode); + break; + case 2: + Events.assertField(e, "hashCode") + .equal(TestCertificate.TWO.hashCode); + break; + case 3: + Events.assertField(e, "hashCode") + .equal(TestCertificate.ONE.hashCode); + break; + default: + System.out.println(events); + throw new Exception("Unexpected position:" + pos); + } + } + } + + /* + * Self signed certificate test + */ + private static void assertEvent2(List events) throws Exception { + for (RecordedEvent e : events) { + int pos = e.getInt("certificatePosition"); + switch (pos) { + case 1: + case 2: + Events.assertField(e, "hashCode") + .equal(TestCertificate.ROOT_CA.hashCode); + break; + default: + System.out.println(events); + throw new Exception("Unexpected position:" + pos); + } + } + } +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/security/logging/LogJvm.java 2018-11-06 08:41:13.415364584 +0000 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.security.logging; + +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public final class LogJvm { + private final static String LOGGING_ENABLED= "LOGGING_ENABLED"; + private final static String LOGGING_DISABLED= "LOGGING_DISABLED"; + + private final static boolean debug = false; + + private final List expectedLogMessages = new ArrayList<>(); + private final Class clazz; + private final boolean loggingEnabled; + + public LogJvm(Class clazz, String[] args) { + this.clazz = clazz; + this.loggingEnabled = Arrays.asList(args).contains(LOGGING_ENABLED); + ensureLogging(args); + } + + private void ensureLogging(String[] args) { + for(String s : args) { + if (s.equals(LOGGING_ENABLED) || s.equals(LOGGING_DISABLED)) { + return; + } + } + throw new RuntimeException(LogJvm.class.getName() + + " requires command line parameter " + LOGGING_ENABLED + + " or " + LOGGING_DISABLED); + } + + public void addExpected(String logMsg) { + expectedLogMessages.add(logMsg); + } + + public void testExpected() throws Exception { + OutputAnalyzer out = launchJVM(); + if (debug) { + System.out.println("STDOUT DEBUG:\n " + out.getStdout()); + System.out.println("\nSTDERR DEBUG:\n " + out.getStderr()); + } + if (loggingEnabled) { + testLoggingEnabled(out); + } else { + testLoggingDisabled(out); + } + } + + public OutputAnalyzer launchJVM() throws Exception { + List args = new ArrayList<>(); + if (loggingEnabled) { + args.add("-Djava.util.logging.config.file=" + + Paths.get(System.getProperty("test.src", "."), "logging.properties")); + } + args.add("--add-exports"); + args.add("java.base/jdk.internal.event=ALL-UNNAMED"); + args.add(clazz.getName()); + System.out.println(args); + OutputAnalyzer out = ProcessTools.executeTestJava(args.toArray(new String[0])); + out.shouldHaveExitValue(0); + return out; + } + + private void testLoggingDisabled(OutputAnalyzer out) { + for (String expected : expectedLogMessages) { + out.shouldNotContain(expected); + } + } + + private void testLoggingEnabled(OutputAnalyzer out) { + for (String expected : expectedLogMessages) { + out.shouldContain(expected); + } + } +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/security/logging/TestJdkSecurityPropertyModificationLog.java 2018-11-06 08:41:14.367364584 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.security.logging; + +import java.security.Security; +import jdk.test.lib.security.TestJdkSecurityPropertyModification; +import static jdk.test.lib.security.TestJdkSecurityPropertyModification.jdkProps; +import static jdk.test.lib.security.TestJdkSecurityPropertyModification.GOOD_VALUE; + +/* + * @test + * @bug 8148188 + * @summary Enhance the security libraries to record events of interest + * @library /test/lib /test/jdk + * @run main/othervm jdk.security.logging.TestJdkSecurityPropertyModificationLog LOGGING_ENABLED + * @run main/othervm jdk.security.logging.TestJdkSecurityPropertyModificationLog LOGGING_DISABLED + */ +public class TestJdkSecurityPropertyModificationLog { + + public static void main(String[] args) throws Exception { + LogJvm l = new LogJvm(SetJdkSecurityProperty.class, args); + for (String s: jdkProps) { + l.addExpected("FINE: JdkSecurityPropertyModification: key:" + + s + ", value:" + GOOD_VALUE); + } + l.testExpected(); + } + + public static class SetJdkSecurityProperty { + public static void main(String[] args) { + TestJdkSecurityPropertyModification.runTest(); + } + } +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/security/logging/TestTLSHandshakeLog.java 2018-11-06 08:41:15.407364584 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.security.logging; + +import jdk.test.lib.security.TestTLSHandshake; + +/* + * @test + * @bug 8148188 + * @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 { + 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); + l.addExpected("Subject:CN=Regression Test"); + l.addExpected("Key type:EC, Length:256"); + l.addExpected("FINE: ValidationChain: " + + TestTLSHandshake.ANCHOR_HASHCODE + + ", " + TestTLSHandshake.HASHCODE); + l.addExpected("SunJSSE Test Serivce"); + l.addExpected("TLSHandshake:"); + l.addExpected("TLSv1.2"); + l.addExpected(TestTLSHandshake.CIPHER_SUITE +", " + TestTLSHandshake.HASHCODE); + l.testExpected(); + } + + public static class TLSHandshake { + public static void main(String[] args) throws Exception { + TestTLSHandshake handshake = new TestTLSHandshake(); + handshake.run(); + } + } +} \ No newline at end of file --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/security/logging/TestX509CertificateLog.java 2018-11-06 08:41:16.359364584 +0000 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.security.logging; + +import java.security.cert.CertificateFactory; +import jdk.test.lib.security.TestCertificate; + +/* + * @test + * @bug 8148188 + * @summary Enhance the security libraries to record events of interest + * @library /test/lib /test/jdk + * @run main/othervm jdk.security.logging.TestX509CertificateLog LOGGING_ENABLED + * @run main/othervm jdk.security.logging.TestX509CertificateLog LOGGING_DISABLED + */ +public class TestX509CertificateLog { + public static void main(String[] args) throws Exception { + LogJvm l = new LogJvm(GenerateX509Certicate.class, args); + l.addExpected( + "FINE: X509Certificate: Alg:" + TestCertificate.ONE.algorithm + + ", Serial:" + TestCertificate.ONE.serialNumber + + ", Subject:" + TestCertificate.ONE.subject + + ", Issuer:" + TestCertificate.ONE.issuer + + ", Key type:" + TestCertificate.ONE.keyType + + ", Length:" + TestCertificate.ONE.keyLength + + ", Hash code:" + TestCertificate.ONE.hashCode); + l.addExpected( + "FINE: X509Certificate: Alg:" + TestCertificate.TWO.algorithm + + ", Serial:" + TestCertificate.TWO.serialNumber + + ", Subject:" + TestCertificate.TWO.subject + + ", Issuer:" + TestCertificate.TWO.issuer + + ", Key type:" + TestCertificate.TWO.keyType + + ", Length:" + TestCertificate.TWO.keyLength + + ", Hash code:" + TestCertificate.TWO.hashCode); + l.testExpected(); + } + + public static class GenerateX509Certicate { + public static void main(String[] args) throws Exception { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + TestCertificate.ONE.generate(cf); + TestCertificate.TWO.generate(cf); + } + } +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/security/logging/TestX509ValidationLog.java 2018-11-06 08:41:17.311364584 +0000 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.security.logging; + +import jdk.test.lib.security.TestCertificate; + +/* + * @test + * @bug 8148188 + * @summary Enhance the security libraries to record events of interest + * @library /test/lib /test/jdk + * @run main/othervm jdk.security.logging.TestX509ValidationLog LOGGING_ENABLED + * @run main/othervm jdk.security.logging.TestX509ValidationLog LOGGING_DISABLED + */ +public class TestX509ValidationLog { + public static void main(String[] args) throws Exception { + LogJvm l = new LogJvm(GenerateCertificateChain.class, args); + l.addExpected("FINE: ValidationChain: " + + TestCertificate.ROOT_CA.hashCode + ", " + + TestCertificate.TWO.hashCode + ", " + + TestCertificate.ONE.hashCode); + l.addExpected("FINE: ValidationChain: " + + TestCertificate.ROOT_CA.hashCode + ", " + + TestCertificate.ROOT_CA.hashCode); + l.testExpected(); + } + + public static class GenerateCertificateChain { + public static void main(String[] args) throws Exception { + TestCertificate.generateChain(false); + // self signed test + TestCertificate.generateChain(true); + + } + } +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/jdk/jdk/security/logging/logging.properties 2018-11-06 08:41:18.199364584 +0000 @@ -0,0 +1,13 @@ +############################################################ +# Configuration file for log testing +# +############################################################ + +handlers= java.util.logging.ConsoleHandler + +.level= FINE + +java.util.logging.ConsoleHandler.level = FINE +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter + +jdk.event.security.level = FINE --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/lib/jdk/test/lib/security/SSLSocketTest.java 2018-11-06 08:41:19.083364584 +0000 @@ -0,0 +1,891 @@ +/* + * Copyright (c) 2016, 2018, 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. + */ + +package jdk.test.lib.security; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; +import java.net.InetSocketAddress; +import java.net.SocketTimeoutException; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.KeyFactory; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Base64; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Template to help speed up your client/server tests. + * + * Two examples that use this template: + * test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java + * test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java + */ +public abstract class SSLSocketTest { + + /* + * Run the test case. + */ + public void run() throws Exception { + bootup(); + } + + /* + * Define the server side application of the test for the specified socket. + */ + protected abstract void runServerApplication(SSLSocket socket) throws Exception; + + /* + * Define the client side application of the test for the specified socket. + * This method is used if the returned value of + * isCustomizedClientConnection() is false. + * + * @param socket may be null is no client socket is generated. + * + * @see #isCustomizedClientConnection() + */ + protected abstract void runClientApplication(SSLSocket socket) throws Exception; + + /* + * Define the client side application of the test for the specified + * server port. This method is used if the returned value of + * isCustomizedClientConnection() is true. + * + * Note that the client need to connect to the server port by itself + * for the actual message exchange. + * + * @see #isCustomizedClientConnection() + */ + protected void runClientApplication(int serverPort) throws Exception { + // blank + } + + /* + * Create an instance of SSLContext for client use. + */ + protected SSLContext createClientSSLContext() throws Exception { + return createSSLContext(trustedCertStrs, + endEntityCertStrs, endEntityPrivateKeys, + endEntityPrivateKeyAlgs, + endEntityPrivateKeyNames, + getClientContextParameters()); + } + + /* + * Create an instance of SSLContext for server use. + */ + protected SSLContext createServerSSLContext() throws Exception { + return createSSLContext(trustedCertStrs, + endEntityCertStrs, endEntityPrivateKeys, + endEntityPrivateKeyAlgs, + endEntityPrivateKeyNames, + getServerContextParameters()); + } + + /* + * The parameters used to configure SSLContext. + */ + protected static final class ContextParameters { + final String contextProtocol; + final String tmAlgorithm; + final String kmAlgorithm; + + ContextParameters(String contextProtocol, + String tmAlgorithm, String kmAlgorithm) { + + this.contextProtocol = contextProtocol; + this.tmAlgorithm = tmAlgorithm; + this.kmAlgorithm = kmAlgorithm; + } + } + + /* + * Get the client side parameters of SSLContext. + */ + protected ContextParameters getClientContextParameters() { + return new ContextParameters("TLS", "PKIX", "NewSunX509"); + } + + /* + * Get the server side parameters of SSLContext. + */ + protected ContextParameters getServerContextParameters() { + return new ContextParameters("TLS", "PKIX", "NewSunX509"); + } + + /* + * Does the client side use customized connection other than + * explicit Socket.connect(), for example, URL.openConnection()? + */ + protected boolean isCustomizedClientConnection() { + return false; + } + + /* + * Configure the server side socket. + */ + protected void configureServerSocket(SSLServerSocket socket) { + + } + + /* + * ============================================= + * Define the client and server side operations. + * + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Is the server ready to serve? + */ + private final CountDownLatch serverCondition = new CountDownLatch(1); + + /* + * Is the client ready to handshake? + */ + private final CountDownLatch clientCondition = new CountDownLatch(1); + + /* + * What's the server port? Use any free port by default + */ + private volatile int serverPort = 0; + + /* + * Define the server side of the test. + */ + private void doServerSide() throws Exception { + // kick start the server side service + SSLContext context = createServerSSLContext(); + SSLServerSocketFactory sslssf = context.getServerSocketFactory(); + SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(serverPort); + configureServerSocket(sslServerSocket); + serverPort = sslServerSocket.getLocalPort(); + + // Signal the client, the server is ready to accept connection. + serverCondition.countDown(); + + // Try to accept a connection in 30 seconds. + SSLSocket sslSocket; + try { + sslServerSocket.setSoTimeout(30000); + sslSocket = (SSLSocket)sslServerSocket.accept(); + } catch (SocketTimeoutException ste) { + // Ignore the test case if no connection within 30 seconds. + System.out.println( + "No incoming client connection in 30 seconds. " + + "Ignore in server side."); + return; + } finally { + sslServerSocket.close(); + } + + // handle the connection + try { + // Is it the expected client connection? + // + // Naughty test cases or third party routines may try to + // connection to this server port unintentionally. In + // order to mitigate the impact of unexpected client + // connections and avoid intermittent failure, it should + // be checked that the accepted connection is really linked + // to the expected client. + boolean clientIsReady = + clientCondition.await(30L, TimeUnit.SECONDS); + + if (clientIsReady) { + // Run the application in server side. + runServerApplication(sslSocket); + } else { // Otherwise, ignore + // We don't actually care about plain socket connections + // for TLS communication testing generally. Just ignore + // the test if the accepted connection is not linked to + // the expected client or the client connection timeout + // in 30 seconds. + System.out.println( + "The client is not the expected one or timeout. " + + "Ignore in server side."); + } + } finally { + sslSocket.close(); + } + } + + /* + * Define the client side of the test. + */ + private void doClientSide() throws Exception { + + // Wait for server to get started. + // + // The server side takes care of the issue if the server cannot + // get started in 90 seconds. The client side would just ignore + // the test case if the serer is not ready. + boolean serverIsReady = + serverCondition.await(90L, TimeUnit.SECONDS); + if (!serverIsReady) { + System.out.println( + "The server is not ready yet in 90 seconds. " + + "Ignore in client side."); + return; + } + + if (isCustomizedClientConnection()) { + // Signal the server, the client is ready to communicate. + clientCondition.countDown(); + + // Run the application in client side. + runClientApplication(serverPort); + + return; + } + + SSLContext context = createClientSSLContext(); + SSLSocketFactory sslsf = context.getSocketFactory(); + + try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) { + try { + sslSocket.connect( + new InetSocketAddress("localhost", serverPort), 15000); + } catch (IOException ioe) { + // The server side may be impacted by naughty test cases or + // third party routines, and cannot accept connections. + // + // Just ignore the test if the connection cannot be + // established. + System.out.println( + "Cannot make a connection in 15 seconds. " + + "Ignore in client side."); + return; + } + + // OK, here the client and server get connected. + + // Signal the server, the client is ready to communicate. + clientCondition.countDown(); + + // There is still a chance in theory that the server thread may + // wait client-ready timeout and then quit. The chance should + // be really rare so we don't consider it until it becomes a + // real problem. + + // Run the application in client side. + runClientApplication(sslSocket); + } + } + + /* + * ============================================= + * Stuffs to customize the SSLContext instances. + */ + + /* + * ======================================= + * 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----- + }; + + // 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", + }; + + /* + * Create an instance of SSLContext with the specified trust/key materials. + */ + private SSLContext createSSLContext( + String[] trustedMaterials, + String[] keyMaterialCerts, + String[] keyMaterialKeys, + String[] keyMaterialKeyAlgs, + String[] keyMaterialKeyNames, + ContextParameters params) throws Exception { + + KeyStore ts = null; // trust store + KeyStore ks = null; // key store + char passphrase[] = "passphrase".toCharArray(); + + // Generate certificate from cert string. + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + // Import the trused certs. + ByteArrayInputStream is; + if (trustedMaterials != null && trustedMaterials.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()); + try { + trustedCert[i] = cf.generateCertificate(is); + } finally { + is.close(); + } + + ts.setCertificateEntry("trusted-cert-" + i, 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) { + ks = KeyStore.getInstance("JKS"); + ks.load(null, null); + + for (int i = 0; i < keyMaterialCerts.length; i++) { + String keyCertStr = keyMaterialCerts[i]; + + // generate the private key. + PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder().decode(keyMaterialKeys[i])); + KeyFactory kf = + KeyFactory.getInstance(keyMaterialKeyAlgs[i]); + PrivateKey priKey = kf.generatePrivate(priKeySpec); + + // generate certificate chain + is = new ByteArrayInputStream(keyCertStr.getBytes()); + Certificate keyCert = null; + try { + keyCert = cf.generateCertificate(is); + } finally { + is.close(); + } + + Certificate[] chain = new Certificate[] { keyCert }; + + // import the key entry. + ks.setKeyEntry("cert-" + keyMaterialKeyNames[i], + priKey, passphrase, chain); + } + } + + // Create an SSLContext object. + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(params.tmAlgorithm); + tmf.init(ts); + + SSLContext context = SSLContext.getInstance(params.contextProtocol); + if (hasKeyMaterials && ks != null) { + KeyManagerFactory kmf = + KeyManagerFactory.getInstance(params.kmAlgorithm); + kmf.init(ks, passphrase); + + context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } else { + context.init(null, tmf.getTrustManagers(), null); + } + + return context; + } + + /* + * ================================================= + * Stuffs to boot up the client-server mode testing. + */ + private Thread clientThread = null; + private Thread serverThread = null; + private volatile Exception serverException = null; + private volatile Exception clientException = null; + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + private static final boolean separateServerThread = false; + + /* + * Boot up the testing, used to drive remainder of the test. + */ + private void bootup() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); + } + } else { + if (clientThread != null) { + clientThread.join(); + } + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + private void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + @Override + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + logException("Server died", e); + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + logException("Server failed", e); + serverException = e; + } + } + } + + private void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + @Override + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + logException("Client died", e); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + logException("Client failed", e); + clientException = e; + } + } + } + + private synchronized void logException(String prefix, Throwable cause) { + System.out.println(prefix + ": " + cause); + cause.printStackTrace(System.out); + } +} --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/lib/jdk/test/lib/security/TestCertificate.java 2018-11-06 08:41:19.907364584 +0000 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.test.lib.security; + +import java.io.ByteArrayInputStream; +import java.security.cert.CertPath; +import java.security.cert.CertPathValidator; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.PKIXParameters; +import java.security.cert.TrustAnchor; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +// Certificates taken from old ValWithAnchorByName testcase *** +public enum TestCertificate { + // Subject: CN=SSLCertificate, O=SomeCompany + // Issuer: CN=Intermediate CA Cert, O=SomeCompany + // Validity: Tue Aug 30 14:37:19 PDT 2016 to Wed Aug 30 14:37:19 PDT 2017 + ONE("1000", + "CN=SSLCertificate, O=SomeCompany", + "CN=Intermediate CA Cert, O=SomeCompany", + -1063259762, + "-----BEGIN CERTIFICATE-----\n" + + "MIIDnTCCAoWgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwNTEUMBIGA1UEChMLU29t\n" + + "ZUNvbXBhbnkxHTAbBgNVBAMTFEludGVybWVkaWF0ZSBDQSBDZXJ0MB4XDTE2MDgz\n" + + "MDIxMzcxOVoXDTE3MDgzMDIxMzcxOVowLzEUMBIGA1UEChMLU29tZUNvbXBhbnkx\n" + + "FzAVBgNVBAMTDlNTTENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" + + "MIIBCgKCAQEAjgv8KKE4CO0rbCjRLA1hXjRiSq30jeusCJ8frbRG+QOBgQ3j6jgc\n" + + "vk5wG1aTu7R4AFn0/HRDMzP9ZbRlZVIbJUTd8YiaNyZeyWapPnxHWrPCd5e1xopk\n" + + "ElieDdEH5FiLGtIrWy56CGA1hfQb1vUVYegyeY+TTtMFVHt0PrmMk4ZRgj/GtVNp\n" + + "BQQYIzaYAcrcWMeCn30ZrhaGAL1hsdgmEVV1wsTD4JeNMSwLwMYem7fg8ondGZIR\n" + + "kZuGtuSdOHu4Xz+mgDNXTeX/Bp/dQFucxCG+FOOM9Hoz72RY2W8YqgL38RlnwYWp\n" + + "nUNxhXWFH6vyINRQVEu3IgahR6HXjxM7LwIDAQABo4G8MIG5MBQGA1UdEQQNMAuC\n" + + "CWxvY2FsaG9zdDAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9s\n" + + "b2NhbGhvc3Q6NDIzMzMwHwYDVR0jBBgwFoAUYT525lwHCI4CmuWs8a7poaeKRJ4w\n" + + "HQYDVR0OBBYEFCaQnOX4L1ovqyfeKuoay+kI+lXgMA4GA1UdDwEB/wQEAwIFoDAd\n" + + "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEB\n" + + "AD8dqQIqFasJcL8lm4mPTsBl0JgNiN8tQcXM7VCvcH+yDvEyh9vudDjuhpSORqPq\n" + + "f1o/EvJ+gfs269mBnYQujYRvmSd6EAcBntv5zn6amOh03o6PqTY9KaUC/mL9hB84\n" + + "Y5/LYioP16sME7egKnlrGUgKh0ZvGzm7c3SYx3Z5YoeFBOkZajc7Jm+cBw/uBQkF\n" + + "a9mLEczIvOgkq1wto8vr2ptH1gEuvFRcorN3muvq34bk40G08+AHlP3fCLFpI3FA\n" + + "IStJLJZRcO+Ib4sOcKuaBGnuMo/QVOCEMDUs6RgiWtSd93OZKFIUOASVp6YIkcSs\n" + + "5/rmc06sICqBjLfPEB68Jjw=\n" + + "-----END CERTIFICATE-----"), + // Subject: CN=Intermediate CA Cert, O=SomeCompany + // Issuer: CN=Root CA Cert, O=SomeCompany + // Validity: Sun Aug 07 14:37:19 PDT 2016 to Tue Aug 07 14:37:19 PDT 2018 + TWO("64", + "CN=Intermediate CA Cert, O=SomeCompany", + "CN=Root CA Cert, O=SomeCompany", + -927189373, + "-----BEGIN CERTIFICATE-----\n" + + "MIIDdjCCAl6gAwIBAgIBZDANBgkqhkiG9w0BAQsFADAtMRQwEgYDVQQKEwtTb21l\n" + + "Q29tcGFueTEVMBMGA1UEAxMMUm9vdCBDQSBDZXJ0MB4XDTE2MDgwNzIxMzcxOVoX\n" + + "DTE4MDgwNzIxMzcxOVowNTEUMBIGA1UEChMLU29tZUNvbXBhbnkxHTAbBgNVBAMT\n" + + "FEludGVybWVkaWF0ZSBDQSBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" + + "CgKCAQEAnJR5CnE7GKlQjigExSJ6hHu302mc0PcA6TDgsIitPYD/r8RBbBuE51OQ\n" + + "7IP7AXmfPUV3/+pO/uxx6mgY5O6XeUl7KadhVPtPcL0BVVevCSOdTMVa3iV4zRpa\n" + + "C6Uy2ouUFnafKnDtlbieggyETUoNgVNJYA9L0XNhtSnENoLHC4Pq0v8OsNtsOWFR\n" + + "NiMTOA49NNDBw85WgPyFAxjqO4z0J0zxdWq3W4rSMB8xrkulv2Rvj3GcfYJK/ab8\n" + + "V1IJ6PMWCpujASY3BzvYPnN7BKuBjbWJPgZdPYfX1cxeG80u0tOuMfWWiNONSMSA\n" + + "7m9y304QA0gKqlrFFn9U4hU89kv1IwIDAQABo4GYMIGVMA8GA1UdEwEB/wQFMAMB\n" + + "Af8wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzABhhZodHRwOi8vbG9jYWxob3N0\n" + + "OjM5MTM0MB8GA1UdIwQYMBaAFJNMsejEyJUB9tiWycVczvpiMVQZMB0GA1UdDgQW\n" + + "BBRhPnbmXAcIjgKa5azxrumhp4pEnjAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcN\n" + + "AQELBQADggEBAE4nOFdW9OirPnRvxihQXYL9CXLuGQz5tr0XgN8wSY6Un9b6CRiK\n" + + "7obgIGimVdhvUC1qdRcwJqgOfJ2/jR5/5Qo0TVp+ww4dHNdUoj73tagJ7jTu0ZMz\n" + + "5Zdp0uwd4RD/syvTeVcbPc3m4awtgEvRgzpDMcSeKPZWInlo7fbnowKSAUAfO8de\n" + + "0cDkxEBkzPIzGNu256cdLZOqOK9wLJ9mQ0zKgi/2NsldNc2pl/6jkGpA6uL5lJsm\n" + + "fo9sDusWNHV1YggqjDQ19hrf40VuuC9GFl/qAW3marMuEzY/NiKVUxty1q1s48SO\n" + + "g5LoEPDDkbygOt7ICL3HYG1VufhC1Q2YY9c=\n" + + "-----END CERTIFICATE-----"), + // Subject: CN=Root CA Cert, O=SomeCompany + // Issuer: CN=Root CA Cert, O=SomeCompany + // Validity: Fri Jul 08 14:37:18 PDT 2016 to Fri Jun 28 14:37:18 PDT 2019 + ROOT_CA("1", + "CN=Root CA Cert, O=SomeCompany", + "CN=Root CA Cert, O=SomeCompany", + -1299818863, + "-----BEGIN CERTIFICATE-----\n" + + "MIIDODCCAiCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAtMRQwEgYDVQQKEwtTb21l\n" + + "Q29tcGFueTEVMBMGA1UEAxMMUm9vdCBDQSBDZXJ0MB4XDTE2MDcwODIxMzcxOFoX\n" + + "DTE5MDYyODIxMzcxOFowLTEUMBIGA1UEChMLU29tZUNvbXBhbnkxFTATBgNVBAMT\n" + + "DFJvb3QgQ0EgQ2VydDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIlN\n" + + "M3WYEqkU2elXEZrV9QSDbDKwyaLEHafLFciH8Edoag3q/7jEzFJxI7JZ831tdbWQ\n" + + "Bm6Hgo+8pvetOFW1BckL8eIjyOONP2CKfFaeMaozsWi1cgxa+rjpU/Rekc+zBqvv\n" + + "y4Sr97TwT6nQiLlgjC1nCfR1SVpO51qoDChS7n785rsKEZxw/p+kkVWSZffU7zN9\n" + + "c645cPg//L/kjiyeKMkaquGQOYS68gQgy8YZXQv1E3l/8e8Ci1s1DYA5wpCbaBqg\n" + + "Tw84Rr4zlUEQBgXzQlRt+mPzeaDpdG1EeGkXrcdkZ+0EMELoOVXOEn6VNsz6vT3I\n" + + "KrnvQBSnN06xq/iWwC0CAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME\n" + + "GDAWgBSTTLHoxMiVAfbYlsnFXM76YjFUGTAdBgNVHQ4EFgQUk0yx6MTIlQH22JbJ\n" + + "xVzO+mIxVBkwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQAAi+Nl\n" + + "sxP9t2IhiZIHRJGSBZuQlXIjwYIwbq3ZWc/ApZ+0oxtl7DYQi5uRNt8/opcGNCHc\n" + + "IY0fG93SbkDubXbxPYBW6D/RUjbz59ZryaP5ym55p1MjHTOqy+AM8g41xNTJikc3\n" + + "UUFXXnckeFbawijCsb7vf71owzKuxgBXi9n1rmXXtncKoA/LrUVXoUlKefdgDnsU\n" + + "sl3Q29eibE3HSqziMMoAOLm0jjekFGWIgLeTtyRYR1d0dNaUwsHTrQpPjxxUTn1x\n" + + "sAPpXKfzPnsYAZeeiaaE75GwbWlHzrNinvxdZQd0zctpfBJfVqD/+lWANlw+rOaK\n" + + "J2GyCaJINsyaI/I2\n" + + "-----END CERTIFICATE-----"); + + public String serialNumber; + public String algorithm; + public String subject; + public String issuer; + public String keyType; + public int hashCode; + public int keyLength; + public String encoded; + + TestCertificate(String serialNumber, String subject, String issuer, + int hashCode, String encoded) { + this.serialNumber = serialNumber; + this.subject = subject; + this.issuer = issuer; + this.algorithm = "SHA256withRSA"; + this.encoded = encoded; + this.hashCode = hashCode; + this.keyType = "RSA"; + this.keyLength = 2048; + } + + public X509Certificate generate(CertificateFactory cf) throws CertificateException { + ByteArrayInputStream is = new ByteArrayInputStream(encoded.getBytes()); + return (X509Certificate) cf.generateCertificate(is); + } + + public static void generateChain(boolean selfSignedTest) throws Exception { + // Do path validation as if it is always Tue, 06 Sep 2016 22:12:21 GMT + // This value is within the lifetimes of all certificates. + Date testDate = new Date(1473199941000L); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate c1 = TestCertificate.ONE.generate(cf); + X509Certificate c2 = TestCertificate.TWO.generate(cf); + X509Certificate ca = TestCertificate.ROOT_CA.generate(cf); + + TrustAnchor ta = new TrustAnchor(ca, null); + CertPathValidator validator = CertPathValidator.getInstance("PKIX"); + + PKIXParameters params = new PKIXParameters(Collections.singleton(ta)); + params.setRevocationEnabled(false); + params.setDate(testDate); + if (!selfSignedTest) { + CertPath path = cf.generateCertPath(List.of(c1, c2)); + validator.validate(path, params); + } else { + CertPath path = cf.generateCertPath(List.of(ca)); + validator.validate(path, params); + } + } +} \ No newline at end of file --- /dev/null 2018-10-30 11:16:55.478215000 +0000 +++ new/test/lib/jdk/test/lib/security/TestTLSHandshake.java 2018-11-06 08:41:21.111364584 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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. + */ + +package jdk.test.lib.security; + +import java.io.*; + +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 int HASHCODE = -1057291798; + public static final int ANCHOR_HASHCODE = 1688661792; + public static final String CERT_SERIAL = "edbec8f705af2514"; + public static final String ANCHOR_CERT_SERIAL = "8e191778b2f331be"; + + public String protocolVersion; + public String peerHost; + public int peerPort; + + @Override + protected void runServerApplication(SSLSocket socket) throws Exception { + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + } + + @Override + protected void runClientApplication(SSLSocket socket) throws Exception { + socket.setEnabledCipherSuites(new String[] { CIPHER_SUITE }); + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + + SSLSession sslSession = socket.getSession(); + protocolVersion = sslSession.getProtocol(); + peerHost = sslSession.getPeerHost(); + peerPort = sslSession.getPeerPort(); + } +}