Skip to content

Commit eac9a05

Browse files
committed
8292033: Move jdk.X509Certificate event logic to JCA layer
Reviewed-by: mbaesken Backport-of: 102b2b32feec4727145be4814eb1a69ef462ff16
1 parent 0056a63 commit eac9a05

File tree

12 files changed

+183
-84
lines changed

12 files changed

+183
-84
lines changed

src/java.base/share/classes/java/security/cert/CertificateFactory.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626
package java.security.cert;
2727

2828
import java.io.InputStream;
29-
import java.util.Collection;
30-
import java.util.Iterator;
31-
import java.util.List;
32-
import java.util.Objects;
3329
import java.security.Provider;
3430
import java.security.Security;
3531
import java.security.NoSuchAlgorithmException;
3632
import java.security.NoSuchProviderException;
33+
import java.util.Collection;
34+
import java.util.Iterator;
35+
import java.util.List;
36+
import java.util.Objects;
3737

3838
import sun.security.jca.*;
3939
import sun.security.jca.GetInstance.Instance;
@@ -352,7 +352,9 @@ public final String getType() {
352352
public final Certificate generateCertificate(InputStream inStream)
353353
throws CertificateException
354354
{
355-
return certFacSpi.engineGenerateCertificate(inStream);
355+
Certificate c = certFacSpi.engineGenerateCertificate(inStream);
356+
JCAUtil.tryCommitCertEvent(c);
357+
return c;
356358
}
357359

358360
/**

src/java.base/share/classes/jdk/internal/event/X509CertificateEvent.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,15 @@
3131
*/
3232

3333
public final class X509CertificateEvent extends Event {
34+
private static final X509CertificateEvent EVENT = new X509CertificateEvent();
35+
36+
/**
37+
* Returns {@code true} if event is enabled, {@code false} otherwise.
38+
*/
39+
public static boolean isTurnedOn() {
40+
return EVENT.isEnabled();
41+
}
42+
3443
public String algorithm;
3544
public String serialNumber;
3645
public String subject;

src/java.base/share/classes/sun/security/jca/JCAUtil.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@
2727

2828
import java.lang.ref.*;
2929
import java.security.*;
30+
import java.security.PublicKey;
31+
import java.security.cert.Certificate;
32+
import java.security.cert.X509Certificate;
33+
34+
import jdk.internal.event.EventHelper;
35+
import jdk.internal.event.X509CertificateEvent;
36+
import sun.security.util.KeyUtil;
3037

3138
/**
3239
* Collection of static utility methods used by the security framework.
@@ -91,6 +98,45 @@ public static SecureRandom getDefSecureRandom() {
9198
}
9299
}
93100
return result;
101+
}
94102

103+
public static void tryCommitCertEvent(Certificate cert) {
104+
if ((X509CertificateEvent.isTurnedOn() || EventHelper.isLoggingSecurity()) &&
105+
(cert instanceof X509Certificate x509)) {
106+
PublicKey pKey = x509.getPublicKey();
107+
String algId = x509.getSigAlgName();
108+
String serNum = x509.getSerialNumber().toString(16);
109+
String subject = x509.getSubjectX500Principal().toString();
110+
String issuer = x509.getIssuerX500Principal().toString();
111+
String keyType = pKey.getAlgorithm();
112+
int length = KeyUtil.getKeySize(pKey);
113+
int hashCode = x509.hashCode();
114+
long beginDate = x509.getNotBefore().getTime();
115+
long endDate = x509.getNotAfter().getTime();
116+
if (X509CertificateEvent.isTurnedOn()) {
117+
X509CertificateEvent xce = new X509CertificateEvent();
118+
xce.algorithm = algId;
119+
xce.serialNumber = serNum;
120+
xce.subject = subject;
121+
xce.issuer = issuer;
122+
xce.keyType = keyType;
123+
xce.keyLength = length;
124+
xce.certificateId = hashCode;
125+
xce.validFrom = beginDate;
126+
xce.validUntil = endDate;
127+
xce.commit();
128+
}
129+
if (EventHelper.isLoggingSecurity()) {
130+
EventHelper.logX509CertificateEvent(algId,
131+
serNum,
132+
subject,
133+
issuer,
134+
keyType,
135+
length,
136+
hashCode,
137+
beginDate,
138+
endDate);
139+
}
140+
}
95141
}
96142
}

src/java.base/share/classes/sun/security/provider/X509Factory.java

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,9 @@
2626
package sun.security.provider;
2727

2828
import java.io.*;
29-
import java.security.PublicKey;
3029
import java.util.*;
3130
import java.security.cert.*;
3231

33-
import jdk.internal.event.EventHelper;
34-
import jdk.internal.event.X509CertificateEvent;
3532
import sun.security.util.KeyUtil;
3633
import sun.security.util.Pem;
3734
import sun.security.x509.*;
@@ -104,8 +101,6 @@ public Certificate engineGenerateCertificate(InputStream is)
104101
}
105102
cert = new X509CertImpl(encoding);
106103
addToCache(certCache, cert.getEncodedInternal(), cert);
107-
// record cert details if necessary
108-
commitEvent(cert);
109104
return cert;
110105
} else {
111106
throw new IOException("Empty input");
@@ -473,7 +468,7 @@ public Collection<? extends java.security.cert.CRL> engineGenerateCRLs(
473468
}
474469
} catch (ParsingException e) {
475470
while (data != null) {
476-
coll.add(new X509CertImpl(data));
471+
coll.add(X509CertImpl.newX509CertImpl(data));
477472
data = readOneBlock(pbis);
478473
}
479474
}
@@ -767,43 +762,4 @@ private static int readBERInternal(InputStream is,
767762
}
768763
return tag;
769764
}
770-
771-
private void commitEvent(X509CertImpl info) {
772-
X509CertificateEvent xce = new X509CertificateEvent();
773-
if (xce.shouldCommit() || EventHelper.isLoggingSecurity()) {
774-
PublicKey pKey = info.getPublicKey();
775-
String algId = info.getSigAlgName();
776-
String serNum = info.getSerialNumber().toString(16);
777-
String subject = info.getSubjectDN().getName();
778-
String issuer = info.getIssuerDN().getName();
779-
String keyType = pKey.getAlgorithm();
780-
int length = KeyUtil.getKeySize(pKey);
781-
int hashCode = info.hashCode();
782-
long beginDate = info.getNotBefore().getTime();
783-
long endDate = info.getNotAfter().getTime();
784-
if (xce.shouldCommit()) {
785-
xce.algorithm = algId;
786-
xce.serialNumber = serNum;
787-
xce.subject = subject;
788-
xce.issuer = issuer;
789-
xce.keyType = keyType;
790-
xce.keyLength = length;
791-
xce.certificateId = hashCode;
792-
xce.validFrom = beginDate;
793-
xce.validUntil = endDate;
794-
xce.commit();
795-
}
796-
if (EventHelper.isLoggingSecurity()) {
797-
EventHelper.logX509CertificateEvent(algId,
798-
serNum,
799-
subject,
800-
issuer,
801-
keyType,
802-
length,
803-
hashCode,
804-
beginDate,
805-
endDate);
806-
}
807-
}
808-
}
809765
}

src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ public OCSPResponse(byte[] bytes) throws IOException {
355355
try {
356356
for (int i = 0; i < derCerts.length; i++) {
357357
X509CertImpl cert =
358-
new X509CertImpl(derCerts[i].toByteArray());
358+
X509CertImpl.newX509CertImpl(derCerts[i].toByteArray());
359359
certs.add(cert);
360360

361361
if (debug != null) {

src/java.base/share/classes/sun/security/provider/certpath/X509CertificatePair.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -240,7 +240,7 @@ private void parse(DerValue val)
240240
}
241241
opt = opt.data.getDerValue();
242242
forward = X509Factory.intern
243-
(new X509CertImpl(opt.toByteArray()));
243+
(X509CertImpl.newX509CertImpl(opt.toByteArray()));
244244
}
245245
break;
246246
case TAG_REVERSE:
@@ -251,7 +251,7 @@ private void parse(DerValue val)
251251
}
252252
opt = opt.data.getDerValue();
253253
reverse = X509Factory.intern
254-
(new X509CertImpl(opt.toByteArray()));
254+
(X509CertImpl.newX509CertImpl(opt.toByteArray()));
255255
}
256256
break;
257257
default:

src/java.base/share/classes/sun/security/x509/X509CertImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
import javax.security.auth.x500.X500Principal;
4343

44+
import sun.security.jca.JCAUtil;
4445
import sun.security.util.*;
4546
import sun.security.provider.X509Factory;
4647

@@ -304,6 +305,13 @@ public X509CertImpl(DerValue derVal) throws CertificateException {
304305
}
305306
}
306307

308+
// helper method to record certificate, if necessary, after construction
309+
public static X509CertImpl newX509CertImpl(byte[] certData) throws CertificateException {
310+
var cert = new X509CertImpl(certData);
311+
JCAUtil.tryCommitCertEvent(cert);
312+
return cert;
313+
}
314+
307315
/**
308316
* Appends the certificate to an output stream.
309317
*

test/jdk/jdk/jfr/event/security/TestX509CertificateEvent.java

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,43 +23,70 @@
2323

2424
package jdk.jfr.event.security;
2525

26-
import java.security.cert.CertificateFactory;
2726
import java.util.List;
2827

2928
import jdk.jfr.Recording;
3029
import jdk.jfr.consumer.RecordedEvent;
3130
import jdk.test.lib.Asserts;
3231
import jdk.test.lib.jfr.EventNames;
3332
import jdk.test.lib.jfr.Events;
33+
import jdk.test.lib.jfr.VoidFunction;
3434
import jdk.test.lib.security.TestCertificate;
3535

3636
/*
3737
* @test
38-
* @bug 8148188
38+
* @bug 8148188 8292033
3939
* @summary Enhance the security libraries to record events of interest
4040
* @key jfr
4141
* @requires vm.hasJFR
42+
* @modules java.base/sun.security.x509 java.base/sun.security.tools.keytool
4243
* @library /test/lib
4344
* @run main/othervm jdk.jfr.event.security.TestX509CertificateEvent
4445
*/
4546
public class TestX509CertificateEvent {
46-
public static void main(String[] args) throws Exception {
47-
try (Recording recording = new Recording()) {
48-
recording.enable(EventNames.X509Certificate);
49-
recording.start();
50-
47+
public static void main(String[] args) throws Throwable {
48+
testCall(() -> {
49+
// test regular cert construction
5150
TestCertificate.ONE.certificate();
5251
TestCertificate.TWO.certificate();
53-
// Generate twice to make sure only one event per certificate is generated
52+
// Generate twice to make sure we (now) capture all generate cert events
5453
TestCertificate.ONE.certificate();
5554
TestCertificate.TWO.certificate();
55+
}, 4, true);
5656

57-
recording.stop();
57+
testCall(() -> {
58+
// test generateCertificates method
59+
TestCertificate.certificates();
60+
}, 2, true);
61+
62+
testCall(() -> {
63+
// test generateCertPath method
64+
TestCertificate.certPath();
65+
}, 4, true);
66+
67+
testCall(() -> {
68+
// test keytool cert generation with JFR enabled
69+
// The keytool test will load the dedicated keystore
70+
// and call CertificateFactory.generateCertificate
71+
// cacerts
72+
TestCertificate.keyToolTest();
73+
}, -1, false);
74+
}
5875

76+
private static void testCall(VoidFunction f, int expected, boolean runAsserts) throws Throwable {
77+
try (Recording recording = new Recording()) {
78+
recording.enable(EventNames.X509Certificate);
79+
recording.start();
80+
f.run();
81+
recording.stop();
5982
List<RecordedEvent> events = Events.fromRecording(recording);
60-
Asserts.assertEquals(events.size(), 2, "Incorrect number of X509Certificate events");
61-
assertEvent(events, TestCertificate.ONE);
62-
assertEvent(events, TestCertificate.TWO);
83+
if (expected >= 0) {
84+
Asserts.assertEquals(events.size(), expected, "Incorrect number of events");
85+
}
86+
if (runAsserts) {
87+
assertEvent(events, TestCertificate.ONE);
88+
assertEvent(events, TestCertificate.TWO);
89+
}
6390
}
6491
}
6592

test/jdk/jdk/jfr/event/security/TestX509ValidationEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
* @key jfr
4040
* @requires vm.hasJFR
4141
* @library /test/lib
42-
* @modules jdk.jfr/jdk.jfr.events
42+
* @modules jdk.jfr/jdk.jfr.events java.base/sun.security.x509 java.base/sun.security.tools.keytool
4343
* @run main/othervm jdk.jfr.event.security.TestX509ValidationEvent
4444
*/
4545
public class TestX509ValidationEvent {

test/jdk/jdk/security/logging/TestX509CertificateLog.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,14 +23,14 @@
2323

2424
package jdk.security.logging;
2525

26-
import java.security.cert.CertificateFactory;
2726
import jdk.test.lib.security.TestCertificate;
2827

2928
/*
3029
* @test
3130
* @bug 8148188
3231
* @summary Enhance the security libraries to record events of interest
3332
* @library /test/lib /test/jdk
33+
* @modules java.base/sun.security.x509 java.base/sun.security.tools.keytool
3434
* @run main/othervm jdk.security.logging.TestX509CertificateLog LOGGING_ENABLED
3535
* @run main/othervm jdk.security.logging.TestX509CertificateLog LOGGING_DISABLED
3636
*/

0 commit comments

Comments
 (0)