Skip to content

Commit 102b2b3

Browse files
committed
8292033: Move jdk.X509Certificate event logic to JCA layer
Reviewed-by: mullan
1 parent 1b94ae1 commit 102b2b3

File tree

12 files changed

+184
-86
lines changed

12 files changed

+184
-86
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
@@ -25,7 +25,14 @@
2525

2626
package sun.security.jca;
2727

28+
import java.security.PublicKey;
2829
import java.security.SecureRandom;
30+
import java.security.cert.Certificate;
31+
import java.security.cert.X509Certificate;
32+
33+
import jdk.internal.event.EventHelper;
34+
import jdk.internal.event.X509CertificateEvent;
35+
import sun.security.util.KeyUtil;
2936

3037
/**
3138
* Collection of static utility methods used by the security framework.
@@ -90,6 +97,45 @@ public static SecureRandom getDefSecureRandom() {
9097
}
9198
}
9299
return result;
100+
}
93101

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

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

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,16 @@
2626
package sun.security.provider;
2727

2828
import java.io.*;
29-
import java.security.PublicKey;
29+
3030
import java.security.cert.*;
3131
import java.util.*;
3232

33-
import jdk.internal.event.EventHelper;
34-
import jdk.internal.event.X509CertificateEvent;
35-
3633
import sun.security.pkcs.PKCS7;
3734
import sun.security.pkcs.ParsingException;
3835
import sun.security.provider.certpath.X509CertPath;
3936
import sun.security.provider.certpath.X509CertificatePair;
4037
import sun.security.util.Cache;
4138
import sun.security.util.DerValue;
42-
import sun.security.util.KeyUtil;
4339
import sun.security.x509.X509CRLImpl;
4440
import sun.security.x509.X509CertImpl;
4541

@@ -116,8 +112,6 @@ public static X509CertImpl cachedGetX509Cert(byte[] encoding)
116112
}
117113
cert = new X509CertImpl(encoding);
118114
addToCache(certCache, cert.getEncodedInternal(), cert);
119-
// record cert details if necessary
120-
commitEvent(cert);
121115
return cert;
122116
}
123117

@@ -478,7 +472,7 @@ public Collection<? extends java.security.cert.CRL> engineGenerateCRLs(
478472
}
479473
} catch (ParsingException e) {
480474
while (data != null) {
481-
coll.add(new X509CertImpl(data));
475+
coll.add(X509CertImpl.newX509CertImpl(data));
482476
data = readOneBlock(pbis);
483477
}
484478
}
@@ -772,43 +766,4 @@ private static int readBERInternal(InputStream is,
772766
}
773767
return tag;
774768
}
775-
776-
private static void commitEvent(X509CertImpl info) {
777-
X509CertificateEvent xce = new X509CertificateEvent();
778-
if (xce.shouldCommit() || EventHelper.isLoggingSecurity()) {
779-
PublicKey pKey = info.getPublicKey();
780-
String algId = info.getSigAlgName();
781-
String serNum = info.getSerialNumber().toString(16);
782-
String subject = info.getSubjectDN().getName();
783-
String issuer = info.getIssuerDN().getName();
784-
String keyType = pKey.getAlgorithm();
785-
int length = KeyUtil.getKeySize(pKey);
786-
int hashCode = info.hashCode();
787-
long beginDate = info.getNotBefore().getTime();
788-
long endDate = info.getNotAfter().getTime();
789-
if (xce.shouldCommit()) {
790-
xce.algorithm = algId;
791-
xce.serialNumber = serNum;
792-
xce.subject = subject;
793-
xce.issuer = issuer;
794-
xce.keyType = keyType;
795-
xce.keyLength = length;
796-
xce.certificateId = hashCode;
797-
xce.validFrom = beginDate;
798-
xce.validUntil = endDate;
799-
xce.commit();
800-
}
801-
if (EventHelper.isLoggingSecurity()) {
802-
EventHelper.logX509CertificateEvent(algId,
803-
serNum,
804-
subject,
805-
issuer,
806-
keyType,
807-
length,
808-
hashCode,
809-
beginDate,
810-
endDate);
811-
}
812-
}
813-
}
814769
}

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
@@ -356,7 +356,7 @@ public OCSPResponse(byte[] bytes) throws IOException {
356356
try {
357357
for (int i = 0; i < derCerts.length; i++) {
358358
X509CertImpl cert =
359-
new X509CertImpl(derCerts[i].toByteArray());
359+
X509CertImpl.newX509CertImpl(derCerts[i].toByteArray());
360360
certs.add(cert);
361361

362362
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

@@ -266,6 +267,13 @@ public X509CertImpl(DerValue derVal) throws CertificateException {
266267
}
267268
}
268269

270+
// helper method to record certificate, if necessary, after construction
271+
public static X509CertImpl newX509CertImpl(byte[] certData) throws CertificateException {
272+
var cert = new X509CertImpl(certData);
273+
JCAUtil.tryCommitCertEvent(cert);
274+
return cert;
275+
}
276+
269277
/**
270278
* Appends the certificate to an output stream.
271279
*

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)