1
+ /*
2
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
+ *
5
+ * This code is free software; you can redistribute it and/or modify it
6
+ * under the terms of the GNU General Public License version 2 only, as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * This code is distributed in the hope that it will be useful, but WITHOUT
10
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
+ * version 2 for more details (a copy is included in the LICENSE file that
13
+ * accompanied this code).
14
+ *
15
+ * You should have received a copy of the GNU General Public License version
16
+ * 2 along with this work; if not, write to the Free Software Foundation,
17
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
+ *
19
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
+ * or visit www.oracle.com if you need additional information or have any
21
+ * questions.
22
+ */
23
+
24
+ /*
25
+ * @test
26
+ * @bug 8296343
27
+ * @summary CPVE thrown on missing content-length in OCSP response
28
+ * @modules java.base/sun.security.x509
29
+ * java.base/sun.security.provider.certpath
30
+ * java.base/sun.security.util
31
+ * @library ../../../../../java/security/testlibrary
32
+ * @build CertificateBuilder SimpleOCSPServer
33
+ * @run main/othervm OCSPNoContentLength
34
+ */
35
+
36
+ import java .io .IOException ;
37
+ import java .math .BigInteger ;
38
+ import java .security .KeyPair ;
39
+ import java .security .KeyPairGenerator ;
40
+ import java .security .KeyStore ;
41
+ import java .security .PublicKey ;
42
+ import java .security .cert .*;
43
+ import java .security .cert .X509Certificate ;
44
+ import java .security .spec .ECGenParameterSpec ;
45
+ import java .util .*;
46
+ import java .util .concurrent .TimeUnit ;
47
+
48
+
49
+ import sun .security .testlibrary .SimpleOCSPServer ;
50
+ import sun .security .testlibrary .CertificateBuilder ;
51
+
52
+ public class OCSPNoContentLength {
53
+
54
+ static String passwd = "passphrase" ;
55
+ static String ROOT_ALIAS = "root" ;
56
+ static String EE_ALIAS = "endentity" ;
57
+
58
+ // Enable debugging for additional output
59
+ static final boolean debug = false ;
60
+
61
+ // PKI components we will need for this test
62
+ static X509Certificate rootCert ; // The root CA certificate
63
+ static X509Certificate eeCert ; // The end entity certificate
64
+ static KeyStore rootKeystore ; // Root CA Keystore
65
+ static KeyStore eeKeystore ; // End Entity Keystore
66
+ static KeyStore trustStore ; // SSL Client trust store
67
+ static SimpleOCSPServer rootOcsp ; // Root CA OCSP Responder
68
+ static int rootOcspPort ; // Port number for root OCSP
69
+
70
+
71
+ public static void main (String [] args ) throws Exception {
72
+
73
+ try {
74
+ createPKI ();
75
+
76
+ CertificateFactory cf = CertificateFactory .getInstance ("X.509" );
77
+ CertPath path = cf .generateCertPath (List .of (eeCert ));
78
+ log ("%s" , path );
79
+
80
+ TrustAnchor anchor = new TrustAnchor (rootCert , null );
81
+ log ("%s" , anchor );
82
+ Set <TrustAnchor > anchors = Set .of (anchor );
83
+
84
+ CertPathValidator validator = CertPathValidator .getInstance ("PKIX" );
85
+ PKIXParameters params = new PKIXParameters (anchors );
86
+ PKIXRevocationChecker prc =
87
+ (PKIXRevocationChecker )validator .getRevocationChecker ();
88
+ params .addCertPathChecker (prc );
89
+
90
+ validator .validate (path , params );
91
+ } finally {
92
+ rootOcsp .stop ();
93
+ }
94
+ }
95
+
96
+
97
+ /**
98
+ * Creates the PKI components necessary for this test, including
99
+ * Root CA, Intermediate CA and SSL server certificates, the keystores
100
+ * for each entity, a client trust store, and starts the OCSP responders.
101
+ */
102
+ private static void createPKI () throws Exception {
103
+ CertificateBuilder cbld = new CertificateBuilder ();
104
+ KeyPairGenerator keyGen = KeyPairGenerator .getInstance ("EC" );
105
+ keyGen .initialize (new ECGenParameterSpec ("secp256r1" ));
106
+ KeyStore .Builder keyStoreBuilder =
107
+ KeyStore .Builder .newInstance ("PKCS12" , null ,
108
+ new KeyStore .PasswordProtection (passwd .toCharArray ()));
109
+
110
+ // Generate Root and EE keys
111
+ KeyPair rootCaKP = keyGen .genKeyPair ();
112
+ log ("Generated Root CA KeyPair" );
113
+ KeyPair eeKP = keyGen .genKeyPair ();
114
+ log ("Generated End Entity KeyPair" );
115
+
116
+ // Set up the Root CA Cert
117
+ cbld .setSubjectName ("CN=Root CA Cert, O=SomeCompany" );
118
+ cbld .setPublicKey (rootCaKP .getPublic ());
119
+ cbld .setSerialNumber (new BigInteger ("1" ));
120
+ // Make a 3 year validity starting from 60 days ago
121
+ long start = System .currentTimeMillis () - TimeUnit .DAYS .toMillis (60 );
122
+ long end = start + TimeUnit .DAYS .toMillis (1085 );
123
+ cbld .setValidity (new Date (start ), new Date (end ));
124
+ addCommonExts (cbld , rootCaKP .getPublic (), rootCaKP .getPublic ());
125
+ addCommonCAExts (cbld );
126
+ // Make our Root CA Cert!
127
+ rootCert = cbld .build (null , rootCaKP .getPrivate (),
128
+ "SHA256withECDSA" );
129
+ log ("Root CA Created:\n %s" , certInfo (rootCert ));
130
+
131
+ // Now build a keystore and add the keys and cert
132
+ rootKeystore = keyStoreBuilder .getKeyStore ();
133
+ Certificate [] rootChain = {rootCert };
134
+ rootKeystore .setKeyEntry (ROOT_ALIAS , rootCaKP .getPrivate (),
135
+ passwd .toCharArray (), rootChain );
136
+
137
+ // Now fire up the OCSP responder
138
+ rootOcsp = new SimpleOCSPServer (rootKeystore , passwd , ROOT_ALIAS , null );
139
+ rootOcsp .enableLog (debug );
140
+ rootOcsp .setNextUpdateInterval (3600 );
141
+ rootOcsp .setDisableContentLength (true );
142
+ rootOcsp .start ();
143
+
144
+ // Wait 5 seconds for server ready
145
+ boolean readyStatus = rootOcsp .awaitServerReady (5 , TimeUnit .SECONDS );
146
+ if (!readyStatus ) {
147
+ throw new RuntimeException ("Server not ready" );
148
+ }
149
+
150
+ rootOcspPort = rootOcsp .getPort ();
151
+ String rootRespURI = "http://localhost:" + rootOcspPort ;
152
+ log ("Root OCSP Responder URI is %s" , rootRespURI );
153
+
154
+ // Now that we have the root keystore and OCSP responder we can
155
+ // create our end entity certificate
156
+ cbld .reset ();
157
+ cbld .setSubjectName ("CN=SSLCertificate, O=SomeCompany" );
158
+ cbld .setPublicKey (eeKP .getPublic ());
159
+ cbld .setSerialNumber (new BigInteger ("4096" ));
160
+ // Make a 1 year validity starting from 7 days ago
161
+ start = System .currentTimeMillis () - TimeUnit .DAYS .toMillis (7 );
162
+ end = start + TimeUnit .DAYS .toMillis (365 );
163
+ cbld .setValidity (new Date (start ), new Date (end ));
164
+
165
+ // Add extensions
166
+ addCommonExts (cbld , eeKP .getPublic (), rootCaKP .getPublic ());
167
+ boolean [] kuBits = {true , false , false , false , false , false ,
168
+ false , false , false };
169
+ cbld .addKeyUsageExt (kuBits );
170
+ List <String > ekuOids = new ArrayList <>();
171
+ ekuOids .add ("1.3.6.1.5.5.7.3.1" );
172
+ ekuOids .add ("1.3.6.1.5.5.7.3.2" );
173
+ cbld .addExtendedKeyUsageExt (ekuOids );
174
+ cbld .addSubjectAltNameDNSExt (Collections .singletonList ("localhost" ));
175
+ cbld .addAIAExt (Collections .singletonList (rootRespURI ));
176
+ // Make our End Entity Cert!
177
+ eeCert = cbld .build (rootCert , rootCaKP .getPrivate (),
178
+ "SHA256withECDSA" );
179
+ log ("SSL Certificate Created:\n %s" , certInfo (eeCert ));
180
+
181
+ // Provide end entity cert revocation info to the Root CA
182
+ // OCSP responder.
183
+ Map <BigInteger , SimpleOCSPServer .CertStatusInfo > revInfo =
184
+ new HashMap <>();
185
+ revInfo .put (eeCert .getSerialNumber (),
186
+ new SimpleOCSPServer .CertStatusInfo (
187
+ SimpleOCSPServer .CertStatus .CERT_STATUS_GOOD ));
188
+ rootOcsp .updateStatusDb (revInfo );
189
+
190
+ // Now build a keystore and add the keys, chain and root cert as a TA
191
+ eeKeystore = keyStoreBuilder .getKeyStore ();
192
+ Certificate [] eeChain = {eeCert , rootCert };
193
+ eeKeystore .setKeyEntry (EE_ALIAS , eeKP .getPrivate (),
194
+ passwd .toCharArray (), eeChain );
195
+ eeKeystore .setCertificateEntry (ROOT_ALIAS , rootCert );
196
+
197
+ // And finally a Trust Store for the client
198
+ trustStore = keyStoreBuilder .getKeyStore ();
199
+ trustStore .setCertificateEntry (ROOT_ALIAS , rootCert );
200
+ }
201
+
202
+ private static void addCommonExts (CertificateBuilder cbld ,
203
+ PublicKey subjKey , PublicKey authKey ) throws IOException {
204
+ cbld .addSubjectKeyIdExt (subjKey );
205
+ cbld .addAuthorityKeyIdExt (authKey );
206
+ }
207
+
208
+ private static void addCommonCAExts (CertificateBuilder cbld )
209
+ throws IOException {
210
+ cbld .addBasicConstraintsExt (true , true , -1 );
211
+ // Set key usage bits for digitalSignature, keyCertSign and cRLSign
212
+ boolean [] kuBitSettings = {true , false , false , false , false , true ,
213
+ true , false , false };
214
+ cbld .addKeyUsageExt (kuBitSettings );
215
+ }
216
+
217
+ /**
218
+ * Helper routine that dumps only a few cert fields rather than
219
+ * the whole toString() output.
220
+ *
221
+ * @param cert an X509Certificate to be displayed
222
+ *
223
+ * @return the String output of the issuer, subject and
224
+ * serial number
225
+ */
226
+ private static String certInfo (X509Certificate cert ) {
227
+ StringBuilder sb = new StringBuilder ();
228
+ sb .append ("Issuer: " ).append (cert .getIssuerX500Principal ()).
229
+ append ("\n " );
230
+ sb .append ("Subject: " ).append (cert .getSubjectX500Principal ()).
231
+ append ("\n " );
232
+ sb .append ("Serial: " ).append (cert .getSerialNumber ()).append ("\n " );
233
+ return sb .toString ();
234
+ }
235
+
236
+ /**
237
+ * Log a message on stdout
238
+ *
239
+ * @param format the format string for the log entry
240
+ * @param args zero or more arguments corresponding to the format string
241
+ */
242
+ private static void log (String format , Object ... args ) {
243
+ System .out .format (format + "\n " , args );
244
+ }
245
+ }
0 commit comments