1 package org.bouncycastle.test.est;
2 
3 
4 import java.io.ByteArrayOutputStream;
5 import java.io.PrintWriter;
6 import java.net.SocketException;
7 import java.security.KeyPair;
8 import java.security.KeyPairGenerator;
9 import java.security.KeyStore;
10 import java.security.PrivateKey;
11 import java.security.Provider;
12 import java.security.SecureRandom;
13 import java.security.Security;
14 import java.security.cert.Certificate;
15 import java.security.cert.TrustAnchor;
16 import java.security.cert.X509Certificate;
17 import java.security.spec.ECGenParameterSpec;
18 import java.util.ArrayList;
19 import java.util.Iterator;
20 import java.util.concurrent.TimeUnit;
21 
22 import javax.crypto.Cipher;
23 import javax.crypto.spec.GCMParameterSpec;
24 import javax.crypto.spec.SecretKeySpec;
25 import javax.net.ssl.KeyManagerFactory;
26 import javax.net.ssl.SSLHandshakeException;
27 
28 import junit.framework.TestCase;
29 import org.bouncycastle.asn1.ASN1EncodableVector;
30 import org.bouncycastle.asn1.x500.X500Name;
31 import org.bouncycastle.asn1.x500.X500NameBuilder;
32 import org.bouncycastle.asn1.x500.style.BCStyle;
33 import org.bouncycastle.asn1.x509.KeyPurposeId;
34 import org.bouncycastle.asn1.x509.KeyUsage;
35 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
36 import org.bouncycastle.cert.X509CertificateHolder;
37 import org.bouncycastle.est.ESTException;
38 import org.bouncycastle.est.ESTService;
39 import org.bouncycastle.est.EnrollmentResponse;
40 import org.bouncycastle.est.HttpAuth;
41 import org.bouncycastle.est.jcajce.ChannelBindingProvider;
42 import org.bouncycastle.est.jcajce.JcaHttpAuthBuilder;
43 import org.bouncycastle.est.jcajce.JcaJceUtils;
44 import org.bouncycastle.est.jcajce.JsseESTServiceBuilder;
45 import org.bouncycastle.jce.provider.BouncyCastleProvider;
46 import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
47 import org.bouncycastle.operator.ContentSigner;
48 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
49 import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
50 import org.bouncycastle.pkcs.PKCS10CertificationRequest;
51 import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
52 import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
53 import org.bouncycastle.util.test.SimpleTest;
54 import org.junit.Assert;
55 import org.junit.Test;
56 
57 public class TestEnroll
58     extends SimpleTest
59 {
60 
getName()61     public String getName()
62     {
63         return "TestEnroll";
64     }
65 
performTest()66     public void performTest()
67         throws Exception
68     {
69         ESTTestUtils.runJUnit(TestEnroll.class);
70     }
71 
72 
73     // Start a server instance that uses basic auth.
74     // But disables the POP validation.
startDefaultServerTLSAndBasicAuth(int delay, boolean popOn)75     private ESTServerUtils.ServerInstance startDefaultServerTLSAndBasicAuth(int delay, boolean popOn)
76         throws Exception
77     {
78         final ESTServerUtils.EstServerConfig config = new ESTServerUtils.EstServerConfig();
79         config.serverCertPemFile = ESTServerUtils.makeRelativeToServerHome("estCA/private/estservercertandkey.pem").getCanonicalPath();
80         config.serverKeyPemFile = ESTServerUtils.makeRelativeToServerHome("estCA/private/estservercertandkey.pem").getCanonicalPath();
81         config.realm = "estreal";
82         config.verbose = true;
83         config.tcpPort = 8443;
84         config.useBasicAuth = true;
85         config.useDigestAuth = false;
86         config.estTRUSTEDCerts = ESTServerUtils.makeRelativeToServerHome("trustedcerts.crt").getCanonicalPath();
87         config.estCACERTSResp = ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt").getCanonicalPath();
88         config.disableHTTPAuth = false;
89         config.enableCheckPOPtoTLSUID = popOn;
90         config.manualEnroll = delay;
91 
92 
93         //
94         // Read in openssl config, and adjust it with the correct path.
95         //
96 
97         String cnf = ESTTestUtils.readToString(ESTServerUtils.makeRelativeToServerHome("/estExampleCA.cnf"));
98         cnf = cnf.replace("= ./estCA", "= " + ESTServerUtils.makeRelativeToServerHome("/estCA").getCanonicalPath());
99         config.openSSLConfigFile = cnf;
100 
101         return ESTServerUtils.startServer(config);
102 
103     }
104 
startDefaultServerTLSAndBasicAuthSpecial(int delay, boolean popOn)105     private ESTServerUtils.ServerInstance startDefaultServerTLSAndBasicAuthSpecial(int delay, boolean popOn)
106         throws Exception
107     {
108         final ESTServerUtils.EstServerConfig config = new ESTServerUtils.EstServerConfig();
109         config.serverCertPemFile = ESTServerUtils.makeRelativeToServerHome("keyusage/estservercertandkey.pem").getCanonicalPath();
110         config.serverKeyPemFile = ESTServerUtils.makeRelativeToServerHome("keyusage/estservercertandkey.pem").getCanonicalPath();
111         config.realm = "estreal";
112         config.verbose = true;
113         config.tcpPort = 8443;
114         config.useBasicAuth = true;
115         config.useDigestAuth = false;
116         config.estTRUSTEDCerts = ESTServerUtils.makeRelativeToServerHome("keyusage/trustedcerts.crt").getCanonicalPath();
117         config.estCACERTSResp = ESTServerUtils.makeRelativeToServerHome("keyusage/bc_cacert.crt").getCanonicalPath();
118         config.disableHTTPAuth = false;
119         config.enableCheckPOPtoTLSUID = popOn;
120         config.manualEnroll = delay;
121 
122 
123         //
124         // Read in openssl config, and adjust it with the correct path.
125         //
126 
127         String cnf = ESTTestUtils.readToString(ESTServerUtils.makeRelativeToServerHome("/estExampleCA.cnf"));
128         cnf = cnf.replace("= ./estCA", "= " + ESTServerUtils.makeRelativeToServerHome("/estCA").getCanonicalPath());
129         config.openSSLConfigFile = cnf;
130 
131         return ESTServerUtils.startServer(config);
132 
133     }
134 
135 
136     /*
137       private ESTServerUtils.ServerInstance startSpecialServer()
138         throws Exception
139     {
140 
141         final ESTServerUtils.EstServerConfig config = new ESTServerUtils.EstServerConfig();
142         config.serverCertPemFile = ESTServerUtils.makeRelativeToServerHome("keyusage/estservercertandkey.pem").getCanonicalPath();
143         config.serverKeyPemFile = ESTServerUtils.makeRelativeToServerHome("keyusage/estservercertandkey.pem").getCanonicalPath();
144         config.realm = "estreal";
145         config.verbose = true;
146         config.tcpPort = 8443;
147         config.useBasicAuth = true;
148         config.estTRUSTEDCerts = ESTServerUtils.makeRelativeToServerHome("keyusage/trustedcerts.crt").getCanonicalPath();
149         config.estCACERTSResp = ESTServerUtils.makeRelativeToServerHome("keyusage/bc_cacert.crt").getCanonicalPath();
150 
151         return ESTServerUtils.startServer(config);
152 
153     }
154 
155      */
156 
157 
158 
159 
160     /**
161      * Test enrollment with digest auth.
162      * <p>
163      * NB: The digest as of 2016-Feb-03 is hard coded in the server.
164      *
165      * @return
166      * @throws Exception
167      */
startDefaultServerWithDigestAuth()168     private ESTServerUtils.ServerInstance startDefaultServerWithDigestAuth()
169         throws Exception
170     {
171 
172         final ESTServerUtils.EstServerConfig config = new ESTServerUtils.EstServerConfig();
173         config.serverCertPemFile = ESTServerUtils.makeRelativeToServerHome("estCA/private/estservercertandkey.pem").getCanonicalPath();
174         config.serverKeyPemFile = ESTServerUtils.makeRelativeToServerHome("estCA/private/estservercertandkey.pem").getCanonicalPath();
175         config.realm = "estrealm";
176         config.verbose = true;
177         config.tcpPort = 8443;
178         config.useBasicAuth = false;
179         config.useDigestAuth = true;
180         config.estTRUSTEDCerts = ESTServerUtils.makeRelativeToServerHome("trustedcerts.crt").getCanonicalPath();
181         config.estCACERTSResp = ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt").getCanonicalPath();
182 
183         //
184         // Read in openssl config, and adjust it with the correct path.
185         //
186 
187         String cnf = ESTTestUtils.readToString(ESTServerUtils.makeRelativeToServerHome("/estExampleCA.cnf"));
188         cnf = cnf.replace("= ./estCA", "= " + ESTServerUtils.makeRelativeToServerHome("/estCA").getCanonicalPath());
189         config.openSSLConfigFile = cnf;
190 
191         return ESTServerUtils.startServer(config);
192 
193     }
194 
195 
196     @Test
testEnrollUsingBasicAuth()197     public void testEnrollUsingBasicAuth()
198         throws Exception
199     {
200         ESTTestUtils.ensureProvider();
201         X509CertificateHolder[] theirCAs = null;
202         ESTServerUtils.ServerInstance serverInstance = null;
203 
204         try
205         {
206             serverInstance = startDefaultServerTLSAndBasicAuth(0, false);
207 
208 
209             ESTService est = new JsseESTServiceBuilder(
210                 "localhost:8443", JcaJceUtils.getCertPathTrustManager(
211                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificates(
212                     ESTServerUtils.makeRelativeToServerHome("/estCA/multicacerts.crt")
213                 )) , null)
214             ).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS").build();
215 
216 
217             //
218             // Make certificate request.
219             //
220 
221             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
222             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
223             kpg.initialize(ecGenSpec, new SecureRandom());
224             KeyPair enrollmentPair = kpg.generateKeyPair();
225 
226             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
227                 new X500Name("CN=Test"),
228                 enrollmentPair.getPublic());
229 
230             PKCS10CertificationRequest csr = pkcs10Builder.build(
231                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
232 
233             EnrollmentResponse enr = est.simpleEnroll(false, csr,
234                 new JcaHttpAuthBuilder("estreal", "estuser", "estpwd".toCharArray())
235                     .setNonceGenerator(new SecureRandom()).setProvider("BC").build());
236             X509Certificate expectedCA = ESTTestUtils.toJavaX509Certificate(ESTTestUtils.readPemCertificate(
237                 ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
238             ));
239 
240             X509CertificateHolder enrolledAsHolder = ESTService.storeToArray(enr.getStore())[0];
241 
242             X509Certificate enrolled = ESTTestUtils.toJavaX509Certificate(enrolledAsHolder);
243 
244             // Will fail if it does not verify.
245             enrolled.verify(expectedCA.getPublicKey(), "BC");
246 
247             TestCase.assertEquals(enrolledAsHolder.getSubject(), csr.getSubject());
248             TestCase.assertEquals(enrolledAsHolder.getSubjectPublicKeyInfo(), csr.getSubjectPublicKeyInfo());
249 
250         }
251         finally
252         {
253             if (serverInstance != null)
254             {
255                 serverInstance.getServer().stop_server();
256             }
257         }
258     }
259 
260 
261     @Test
testEnrollUsingBasicAuthWithDelay()262     public void testEnrollUsingBasicAuthWithDelay()
263         throws Exception
264     {
265         ESTTestUtils.ensureProvider();
266         X509CertificateHolder[] theirCAs = null;
267         ESTServerUtils.ServerInstance serverInstance = null;
268 
269         try
270         {
271             serverInstance = startDefaultServerTLSAndBasicAuth(5, false);
272 
273             ESTService est = new JsseESTServiceBuilder(
274                 "localhost:8443", JcaJceUtils.getCertPathTrustManager(
275                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
276                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
277                 )), null)
278             ).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS").build();
279 
280             //
281             // Make certificate request.
282             //
283 
284             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
285             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
286             kpg.initialize(ecGenSpec, new SecureRandom());
287             KeyPair enrollmentPair = kpg.generateKeyPair();
288 
289             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
290                 new X500Name("CN=Test"),
291                 enrollmentPair.getPublic());
292 
293             PKCS10CertificationRequest csr = pkcs10Builder.build(
294                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
295 
296             EnrollmentResponse enr = est.simpleEnroll(false, csr, new HttpAuth("estreal", "estuser", "estpwd".toCharArray(), new SecureRandom(), new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()));
297 
298 
299             Assert.assertFalse("Can Retry is true.", enr.canRetry());
300             Assert.assertNull("Store is null", enr.getStore());
301             Assert.assertFalse("Must not be completed:?", enr.isCompleted());
302 
303             System.out.println(enr.getNotBefore() - System.currentTimeMillis());
304             Assert.assertTrue("Future time reasonable?", enr.getNotBefore() - System.currentTimeMillis() > 2000);
305 
306             int max = 100;
307             while (!enr.canRetry() && --max > 0)
308             {
309                 Thread.sleep(500);
310             }
311             Assert.assertTrue("Wait looped out.", max > 0);
312 
313             Assert.assertTrue("Can we retry?", enr.canRetry());
314 
315 
316             EnrollmentResponse entTriedAgain = est.simpleEnroll(enr);
317 
318             Assert.assertTrue("Must be completed:?", entTriedAgain.isCompleted());
319 
320             X509Certificate expectedCA = ESTTestUtils.toJavaX509Certificate(ESTTestUtils.readPemCertificate(
321                 ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
322             ));
323 
324             X509CertificateHolder enrolledAsHolder = ESTService.storeToArray(entTriedAgain.getStore())[0];
325 
326             X509Certificate enrolled = ESTTestUtils.toJavaX509Certificate(enrolledAsHolder);
327 
328             // Will fail if it does not verify.
329             enrolled.verify(expectedCA.getPublicKey(), "BC");
330 
331             TestCase.assertEquals(enrolledAsHolder.getSubject(), csr.getSubject());
332             TestCase.assertEquals(enrolledAsHolder.getSubjectPublicKeyInfo(), csr.getSubjectPublicKeyInfo());
333 
334 
335         }
336         finally
337         {
338             if (serverInstance != null)
339             {
340                 serverInstance.getServer().stop_server();
341             }
342         }
343     }
344 
345 
346     /**
347      * Perform enrollment using digest auth.
348      *
349      * @throws Exception
350      */
351     @Test
testEnrollUsingDigestAuth()352     public void testEnrollUsingDigestAuth()
353         throws Exception
354     {
355         ESTTestUtils.ensureProvider();
356         X509CertificateHolder[] theirCAs = null;
357         ESTServerUtils.ServerInstance serverInstance = null;
358         try
359         {
360             serverInstance = startDefaultServerWithDigestAuth();
361 
362 
363             ESTService est = new JsseESTServiceBuilder(
364                 "localhost:8443", JcaJceUtils.getCertPathTrustManager(
365                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
366                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
367                 )), null)
368             ).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS").build();
369             //
370             // Make certificate request.
371             //
372 
373             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
374             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
375             kpg.initialize(ecGenSpec, new SecureRandom());
376             KeyPair enrollmentPair = kpg.generateKeyPair();
377 
378             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(new X500Name("CN=Test"), enrollmentPair.getPublic());
379 
380             PKCS10CertificationRequest csr = pkcs10Builder.build(
381                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
382 
383             SecureRandom nonceRandom = new SecureRandom();
384             EnrollmentResponse enr = est.simpleEnroll(false, csr,
385                 new JcaHttpAuthBuilder("estuser", "estpwd".toCharArray()).setNonceGenerator(nonceRandom).setProvider("BC").build());
386             X509Certificate expectedCA = ESTTestUtils.toJavaX509Certificate(ESTTestUtils.readPemCertificate(
387                 ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
388             ));
389 
390             X509CertificateHolder enrolledAsHolder = ESTService.storeToArray(enr.getStore())[0];
391 
392             X509Certificate enrolled = ESTTestUtils.toJavaX509Certificate(enrolledAsHolder);
393 
394             // Will fail if it does not verify.
395             enrolled.verify(expectedCA.getPublicKey(), "BC");
396 
397             TestCase.assertEquals(enrolledAsHolder.getSubject(), csr.getSubject());
398             TestCase.assertEquals(enrolledAsHolder.getSubjectPublicKeyInfo(), csr.getSubjectPublicKeyInfo());
399         }
400         finally
401         {
402             if (serverInstance != null)
403             {
404                 serverInstance.getServer().stop_server();
405             }
406         }
407     }
408 
409 
410     /**
411      * @return [privateKey, X509Certificate]
412      * @throws Exception
413      */
bogusCAGenerator()414     private static Object[] bogusCAGenerator()
415         throws Exception
416     {
417         //
418         // Create a self signed certificate to tend as trust anchor that will
419         // not be part of the servers path.
420         //
421 
422         ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
423         KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
424         kpg.initialize(ecGenSpec, new SecureRandom());
425         KeyPair originalKeyPair = kpg.generateKeyPair();
426 
427         X500NameBuilder builder = new X500NameBuilder();
428         builder.addRDN(BCStyle.C, "AI");
429         builder.addRDN(BCStyle.CN, "BogusCA");
430         builder.addRDN(BCStyle.O, "BogusCA providers.");
431         builder.addRDN(BCStyle.L, "Atlantis");
432 
433         X500Name name = builder.build();
434 
435         return new Object[]{originalKeyPair.getPrivate(), ESTTestUtils.createSelfsignedCert("SHA256WITHECDSA",
436             name,
437             SubjectPublicKeyInfo.getInstance(originalKeyPair.getPublic().getEncoded()),
438             originalKeyPair.getPrivate(),
439             1
440         )};
441     }
442 
443 
444     /**
445      * Test enrollment using TLS do do the client authentication.
446      * In this test we are going to use the BC API to generate a client certificate that the server will NOT accept.
447      *
448      * @throws Exception
449      */
450     @Test
testEnrollUsingBogusTLSClientAuthAndBasicAuth()451     public void testEnrollUsingBogusTLSClientAuthAndBasicAuth()
452         throws Exception
453     {
454         ESTTestUtils.ensureProvider();
455 
456         X509CertificateHolder caCert = ESTTestUtils.readPemCertificate(
457             ESTServerUtils.makeRelativeToServerHome("/extCA/cacert.crt")
458         );
459 
460         PrivateKey caPrivateKey = ESTTestUtils.readPemPrivateKey(
461             ESTServerUtils.makeRelativeToServerHome("/extCA/private/cakey.pem"), "ECDSA"
462         );
463 
464 
465         Object[] bogusCA = bogusCAGenerator();
466 
467 
468         //
469         // Make client certificate that the server should accept, create the key.
470         //
471 
472         ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
473         KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
474         kpg.initialize(ecGenSpec, new SecureRandom());
475         KeyPair originalKeyPair = kpg.generateKeyPair();
476 
477         //
478         // Subject DN
479         //
480         X500NameBuilder builder = new X500NameBuilder();
481         builder.addRDN(BCStyle.C, "AU");
482         builder.addRDN(BCStyle.CN, "Bunyip Bluegum");
483         builder.addRDN(BCStyle.O, "Pudding Protectors");
484         builder.addRDN(BCStyle.L, "Victoria");
485 
486         X500Name name = builder.build();
487 
488         KeyUsage keyUsage = new KeyUsage(KeyUsage.keyCertSign
489             | KeyUsage.digitalSignature | KeyUsage.keyEncipherment
490             | KeyUsage.dataEncipherment | KeyUsage.cRLSign);
491 
492         ASN1EncodableVector purposes = new ASN1EncodableVector();
493         purposes.add(KeyPurposeId.id_kp_serverAuth);
494         purposes.add(KeyPurposeId.id_kp_clientAuth);
495         purposes.add(KeyPurposeId.anyExtendedKeyUsage);
496 
497 
498         X509Certificate clientTLSCert = ESTTestUtils.createASignedCert("SHA256WITHECDSA",
499             name,
500             SubjectPublicKeyInfo.getInstance(originalKeyPair.getPublic().getEncoded()),
501             new X500Name(((X509Certificate)bogusCA[1]).getSubjectDN().getName()),
502             ((PrivateKey)bogusCA[0]),
503             1, purposes, keyUsage
504         );
505 
506 
507         System.out.println(clientTLSCert.toString());
508 
509 
510         //
511         // Make keystore for client JSSE client auth.
512         //
513         KeyStore clientKeyStore = KeyStore.getInstance("JKS");
514         clientKeyStore.load(null);
515 
516         char[] clientKeyStorePass = "tstpass".toCharArray();
517 
518         clientKeyStore.setKeyEntry(
519             "estuser", // This is hardcoded into the test server.
520             originalKeyPair.getPrivate(), clientKeyStorePass,
521             new Certificate[]{
522                 clientTLSCert
523             });
524 
525         clientKeyStore.store(new ByteArrayOutputStream(), clientKeyStorePass);
526 
527 
528         //
529         // Keypair for CSR we wish to enrole.
530         //
531 
532 
533         kpg.initialize(ecGenSpec);
534         KeyPair enrollmentPair = kpg.generateKeyPair();
535 
536 
537         ESTTestUtils.ensureProvider();
538         final ESTServerUtils.ServerInstance serverInstance = startDefaultServerTLSAndBasicAuth(0, false);
539         try
540         {
541 
542             //
543             // Set server trust anchor so client can validate server.
544             //
545 
546             TrustAnchor ta = new TrustAnchor(
547                 ESTTestUtils.toJavaX509Certificate(
548                     ESTTestUtils.readPemCertificate(
549                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
550                     )
551                 ), null);
552 
553 
554             JsseESTServiceBuilder estBuilder = new JsseESTServiceBuilder(
555                 "localhost:8443", JcaJceUtils.getCertPathTrustManager(
556                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
557                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
558                 )), null)
559             ).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
560 
561             estBuilder.withKeyManagers(JcaJceUtils.createKeyManagerFactory(KeyManagerFactory.getDefaultAlgorithm(), null, clientKeyStore, clientKeyStorePass).getKeyManagers());
562 
563 
564             ESTService est = estBuilder.build();
565 
566             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
567                 new X500Name("CN=Test"),
568                 enrollmentPair.getPublic());
569 
570             PKCS10CertificationRequest csr = pkcs10Builder.build(
571                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
572 
573             //
574             // Even though we are using TLS we still need to use an HTTP auth.
575             //
576 
577             try
578             {
579                 EnrollmentResponse enr = est.simpleEnroll(
580                     false,
581                     csr,
582                     new HttpAuth("estreal", "estuser", "estpwd".toCharArray(), new SecureRandom(), new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()));
583             }
584             catch (Exception ex)
585             {
586                 Assert.assertEquals("Only ESTException", ex.getClass(), ESTException.class);
587 
588                 // NB: My assumption is that it depends on how the server hangs up
589                 // but we either get a SSL handshake exception or a Socket exception.
590                 // TODO might be a race.
591                 Assert.assertTrue("Either SocketException or SSLHandshakeException", (ex.getCause() instanceof SocketException || ex.getCause() instanceof SSLHandshakeException));
592             }
593 
594 
595         }
596         finally
597         {
598             serverInstance.getServer().stop_server();
599         }
600     }
601 
602 
603     /**
604      * Test enrollment using TLS do do the client authentication.
605      * In this test we are going to use the BC API to generate a client certificate that the server will accept.
606      *
607      * @throws Exception
608      */
609     @Test
testEnrollUsingTLSClientAuthAndBasicAuth()610     public void testEnrollUsingTLSClientAuthAndBasicAuth()
611         throws Exception
612     {
613         ESTTestUtils.ensureProvider();
614 
615         X509CertificateHolder caCert = ESTTestUtils.readPemCertificate(
616             ESTServerUtils.makeRelativeToServerHome("/extCA/cacert.crt")
617         );
618 
619         PrivateKey caPrivateKey = ESTTestUtils.readPemPrivateKey(
620             ESTServerUtils.makeRelativeToServerHome("/extCA/private/cakey.pem"), "ECDSA"
621         );
622 
623         //
624         // Make client certificate that the server should accept, create the key.
625         //
626 
627         ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
628         KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
629         kpg.initialize(ecGenSpec, new SecureRandom());
630         KeyPair originalKeyPair = kpg.generateKeyPair();
631 
632         //
633         // Subject DN
634         //
635         X500NameBuilder builder = new X500NameBuilder();
636         builder.addRDN(BCStyle.C, "AU");
637         builder.addRDN(BCStyle.CN, "Bunyip Bluegum");
638         builder.addRDN(BCStyle.O, "Pudding Protectors");
639         builder.addRDN(BCStyle.L, "Victoria");
640 
641         X500Name name = builder.build();
642 
643         KeyUsage keyUsage = new KeyUsage(KeyUsage.keyCertSign
644             | KeyUsage.digitalSignature | KeyUsage.keyEncipherment
645             | KeyUsage.dataEncipherment | KeyUsage.cRLSign);
646 
647         ASN1EncodableVector purposes = new ASN1EncodableVector();
648         purposes.add(KeyPurposeId.id_kp_serverAuth);
649         purposes.add(KeyPurposeId.id_kp_clientAuth);
650         purposes.add(KeyPurposeId.anyExtendedKeyUsage);
651 
652 
653         X509Certificate clientTLSCert = ESTTestUtils.createASignedCert("SHA256WITHECDSA",
654             name,
655             SubjectPublicKeyInfo.getInstance(originalKeyPair.getPublic().getEncoded()),
656             caCert.getSubject(),
657             caPrivateKey,
658             1, purposes, keyUsage
659         );
660 
661 
662         //
663         // Make keystore for client JSSE client auth.
664         //
665         KeyStore clientKeyStore = KeyStore.getInstance("JKS");
666         clientKeyStore.load(null);
667 
668         char[] clientKeyStorePass = "tstpass".toCharArray();
669 
670         clientKeyStore.setKeyEntry(
671             "estuser", // This is hardcoded into the test server.
672             originalKeyPair.getPrivate(), clientKeyStorePass,
673             new Certificate[]{
674                 //  ESTTestUtils.toJavaX509Certificate(caCert),
675                 clientTLSCert
676             });
677 
678         clientKeyStore.store(new ByteArrayOutputStream(), clientKeyStorePass);
679 
680 
681         //
682         // Keypair for CSR we wish to enrole.
683         //
684 
685 
686         kpg.initialize(ecGenSpec);
687         KeyPair enrollmentPair = kpg.generateKeyPair();
688 
689 
690         ESTTestUtils.ensureProvider();
691         final ESTServerUtils.ServerInstance serverInstance = startDefaultServerTLSAndBasicAuth(0, false);
692         try
693         {
694 
695             //
696             // Set server trust anchor so client can validate server.
697             //
698 
699 
700             TrustAnchor ta = new TrustAnchor(
701                 ESTTestUtils.toJavaX509Certificate(
702                     ESTTestUtils.readPemCertificate(
703                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
704                     )
705                 ), null);
706 
707 
708             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
709                 new X500Name("CN=Test"),
710                 enrollmentPair.getPublic());
711 
712             PKCS10CertificationRequest csr = pkcs10Builder.build(
713                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
714 
715             JsseESTServiceBuilder estServiceBuilder = new JsseESTServiceBuilder(
716                 "localhost:8443", JcaJceUtils.getCertPathTrustManager(
717                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
718                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
719                 )), null)
720             ).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
721 
722             estServiceBuilder.withKeyManagers(JcaJceUtils.createKeyManagerFactory(KeyManagerFactory.getDefaultAlgorithm(), null, clientKeyStore, clientKeyStorePass).getKeyManagers());
723 
724             ESTService est = estServiceBuilder.build();
725 
726 
727             //
728             // Even though we are using TLS we still need to use an HTTP auth.
729             //
730 
731             EnrollmentResponse enr = est.simpleEnroll(
732                 false,
733                 csr,
734                 new JcaHttpAuthBuilder("estreal", "estuser", "estpwd".toCharArray())
735                     .setNonceGenerator(new SecureRandom()).setProvider("BC").build());
736 
737             X509Certificate expectedCA = ESTTestUtils.toJavaX509Certificate(ESTTestUtils.readPemCertificate(
738                 ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
739             ));
740 
741             X509CertificateHolder enrolledAsHolder = ESTService.storeToArray(enr.getStore())[0];
742 
743             X509Certificate enrolled = ESTTestUtils.toJavaX509Certificate(enrolledAsHolder);
744 
745             // Will fail if it does not verify.
746             enrolled.verify(expectedCA.getPublicKey(), "BC");
747 
748             TestCase.assertEquals(enrolledAsHolder.getSubject(), csr.getSubject());
749             TestCase.assertEquals(enrolledAsHolder.getSubjectPublicKeyInfo(), csr.getSubjectPublicKeyInfo());
750 
751         }
752         finally
753         {
754             serverInstance.getServer().stop_server();
755         }
756     }
757 
758 
759     /**
760      * Test enrollment using TLS do do the client authentication.
761      * In this test we are going to use the BC API to generate a client certificate that the server will accept.
762      * This test uses the Bouncycastle SSL provider as it gives access to RFC5929 Channel Bindings.
763      *
764      * @throws Exception
765      */
766     @Test()
testEnrollUsingTLSClientAuthAndPOP()767     public void testEnrollUsingTLSClientAuthAndPOP()
768         throws Exception
769     {
770 
771 //        ESTTestUtils.ensureProvider(BouncyCastleJsseProvider.PROVIDER_NAME);
772         ESTTestUtils.ensureProvider();
773 
774         X509CertificateHolder caCert = ESTTestUtils.readPemCertificate(
775             ESTServerUtils.makeRelativeToServerHome("/extCA/cacert.crt")
776         );
777 
778         PrivateKey caPrivateKey = ESTTestUtils.readPemPrivateKey(
779             ESTServerUtils.makeRelativeToServerHome("/extCA/private/cakey.pem"), "ECDSA"
780         );
781 
782         //
783         // Make client certificate that the server should accept, create the key.
784         //
785 
786         ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
787         KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
788         kpg.initialize(ecGenSpec, new SecureRandom());
789         KeyPair originalKeyPair = kpg.generateKeyPair();
790 
791         //
792         // Subject DN
793         //
794         X500NameBuilder builder = new X500NameBuilder();
795         builder.addRDN(BCStyle.C, "AU");
796         builder.addRDN(BCStyle.CN, "Bunyip Bluegum");
797         builder.addRDN(BCStyle.O, "Pudding Protectors");
798         builder.addRDN(BCStyle.L, "Victoria");
799 
800         X500Name name = builder.build();
801 
802         KeyUsage keyUsage = new KeyUsage(KeyUsage.keyCertSign
803             | KeyUsage.digitalSignature | KeyUsage.keyEncipherment
804             | KeyUsage.dataEncipherment | KeyUsage.cRLSign);
805 
806         ASN1EncodableVector purposes = new ASN1EncodableVector();
807         purposes.add(KeyPurposeId.id_kp_serverAuth);
808         purposes.add(KeyPurposeId.id_kp_clientAuth);
809         purposes.add(KeyPurposeId.anyExtendedKeyUsage);
810 
811 
812         X509Certificate clientTLSCert = ESTTestUtils.createASignedCert("SHA256WITHECDSA",
813             name,
814             SubjectPublicKeyInfo.getInstance(originalKeyPair.getPublic().getEncoded()),
815             caCert.getSubject(),
816             caPrivateKey,
817             1, purposes, keyUsage
818         );
819 
820 
821         //
822         // Make keystore for client JSSE client auth.
823         //
824         KeyStore clientKeyStore = KeyStore.getInstance("JKS");
825         clientKeyStore.load(null);
826 
827         char[] clientKeyStorePass = "tstpass".toCharArray();
828 
829         clientKeyStore.setKeyEntry(
830             "estuser", // This is hardcoded into the test server.
831             originalKeyPair.getPrivate(), clientKeyStorePass,
832             new Certificate[]{
833                 //  ESTTestUtils.toJavaX509Certificate(caCert),
834                 clientTLSCert
835             });
836 
837         clientKeyStore.store(new ByteArrayOutputStream(), clientKeyStorePass);
838 
839         //
840         // Keypair for CSR we wish to enroll.
841         //
842 
843         kpg.initialize(ecGenSpec);
844         KeyPair enrollmentPair = kpg.generateKeyPair();
845 
846 
847         ESTTestUtils.ensureProvider();
848         final ESTServerUtils.ServerInstance serverInstance = startDefaultServerTLSAndBasicAuth(0, true);
849         try
850         {
851             //
852             // Set server trust anchor so client can validate server.
853             //
854 
855             TrustAnchor ta = new TrustAnchor(
856                 ESTTestUtils.toJavaX509Certificate(
857                     ESTTestUtils.readPemCertificate(
858                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
859                     )
860                 ), null);
861 
862             ChannelBindingProvider bcChannelBindingProvider = new BCChannelBindingProvider();
863 
864 
865             JsseESTServiceBuilder estServiceBuilder = new JsseESTServiceBuilder("localhost:8443", JcaJceUtils.getCertPathTrustManager(
866                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
867                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
868                 )), null));
869 
870             estServiceBuilder.withKeyManagers(JcaJceUtils.createKeyManagerFactory("X509", null, clientKeyStore, clientKeyStorePass).getKeyManagers())
871                .withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
872 
873 
874             ESTService est = estServiceBuilder
875                 .withChannelBindingProvider(bcChannelBindingProvider)
876 
877                 .addCipherSuites(new String[]{
878                     "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
879                     "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
880                     "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
881                     "TLS_ECDHE_RSA_WITH_NULL_SHA",
882                     "TLS_RSA_WITH_AES_128_CCM",
883                     "TLS_RSA_WITH_AES_256_CBC_SHA",
884                     "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
885                     "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
886                     "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
887                     "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
888                     //  "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
889                     "TLS_ECDHE_ECDSA_WITH_AES_256_CCM",
890                     "TLS_RSA_WITH_AES_256_CBC_SHA256",
891                     "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
892                     "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
893                     "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
894                     "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
895                     "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",
896                     "TLS_RSA_WITH_AES_256_CCM_8",
897                     "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
898                     "TLS_ECDHE_ECDSA_WITH_NULL_SHA",
899                     "TLS_RSA_WITH_NULL_SHA256",
900                     "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
901                     "TLS_RSA_WITH_AES_128_CBC_SHA256",
902                     "TLS_RSA_WITH_AES_128_GCM_SHA256",
903                     "TLS_RSA_WITH_AES_256_CCM",
904                     "TLS_RSA_WITH_AES_256_GCM_SHA384",
905                     "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
906                     "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
907                     "TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
908                     "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
909                     "TLS_DHE_RSA_WITH_AES_256_CCM_8",
910                     "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
911                     "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",
912                     "TLS_RSA_WITH_AES_128_CBC_SHA",
913                     "TLS_DHE_RSA_WITH_AES_128_CCM_8",
914                     "TLS_RSA_WITH_NULL_SHA",
915                     "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
916                     "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
917                     "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
918                     "TLS_RSA_WITH_AES_128_CCM_8",
919                     "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
920                     "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
921                     "TLS_DHE_RSA_WITH_AES_256_CCM",
922                     "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
923                     "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
924                     "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
925                     "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
926                     "TLS_DHE_RSA_WITH_AES_128_CCM",
927                     "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
928                     "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
929                     "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
930                     "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"})
931                 .build();
932 
933             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
934                 new X500Name("CN=Test"),
935                 enrollmentPair.getPublic());
936             ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate());
937 
938             //
939             // Even though we are using TLS we still need to use an HTTP auth.
940             //
941             EnrollmentResponse enr = est.simpleEnrollPoP(
942                 false,
943                 pkcs10Builder,
944                 contentSigner,
945                 new JcaHttpAuthBuilder("estreal", "estuser", "estpwd".toCharArray()).setProvider("BC").setNonceGenerator(new SecureRandom()).build());
946 
947 
948             X509Certificate expectedCA = ESTTestUtils.toJavaX509Certificate(ESTTestUtils.readPemCertificate(
949                 ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
950             ));
951 
952             X509CertificateHolder enrolledAsHolder = ESTService.storeToArray(enr.getStore())[0];
953 
954             X509Certificate enrolled = ESTTestUtils.toJavaX509Certificate(enrolledAsHolder);
955 
956             // Will fail if it does not verify.
957             enrolled.verify(expectedCA.getPublicKey(), "BC");
958 
959             //
960             // Other aspects of CSR testing covered elsewhere
961             //
962 
963             System.out.println(ESTTestUtils.toJavaX509Certificate(enrolled));
964 
965         }
966         finally
967         {
968             serverInstance.getServer().stop_server();
969         }
970     }
971 
972     @Test()
testResponseWith401AndNoAuth()973     public void testResponseWith401AndNoAuth()
974         throws Exception
975     {
976         ESTTestUtils.ensureProvider();
977         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
978 
979         PrintWriter pw = new PrintWriter(responseData);
980         pw.print("HTTP/1.1 401 Unauthorized\n" +
981             "Status: 401 Unauthorized\n" +
982             "Content-Length: 0\n\n");
983         pw.flush();
984 
985 
986         //
987         // Test content length enforcement.
988         // Fail when content-length = read limit.
989         //
990         HttpResponder res = new HttpResponder();
991         try
992         {
993             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
994             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
995             kpg.initialize(ecGenSpec, new SecureRandom());
996             KeyPair enrollmentPair = kpg.generateKeyPair();
997 
998 
999             TrustAnchor ta = new TrustAnchor(
1000                 ESTTestUtils.toJavaX509Certificate(
1001                     ESTTestUtils.readPemCertificate(
1002                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1003                     )
1004                 ), null);
1005 
1006 
1007             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1008                 new X500Name("CN=Test"),
1009                 enrollmentPair.getPublic());
1010 
1011             PKCS10CertificationRequest csr = pkcs10Builder.build(
1012                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1013 
1014             //
1015             // Even though we are using TLS we still need to use an HTTP auth.
1016             //
1017 
1018             int port = res.open(responseData.toByteArray());
1019 
1020             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1021                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1022                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1023                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1024                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1025 
1026             builder.addCipherSuites(res.getSupportedCipherSuites());
1027 
1028 
1029             try
1030             {
1031                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr, null);
1032                 Assert.fail("Must throw exception.");
1033             }
1034             catch (Exception t)
1035             {
1036                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1037             }
1038 
1039         }
1040         catch (Exception ex)
1041         {
1042             ex.printStackTrace();
1043         }
1044         finally
1045         {
1046             res.close();
1047         }
1048 
1049         res.getFinished().await(5, TimeUnit.SECONDS);
1050 
1051     }
1052 
1053 
1054     @Test()
testResponseWith400()1055     public void testResponseWith400()
1056         throws Exception
1057     {
1058         ESTTestUtils.ensureProvider();
1059         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1060 
1061         PrintWriter pw = new PrintWriter(responseData);
1062         pw.print("HTTP/1.1 400 Bad Request\n" +
1063             "Status: 400 Bad Request\n" +
1064             "Content-Length: 0\n\n");
1065         pw.flush();
1066 
1067         //
1068         // Test content length enforcement.
1069         // Fail when content-length = read limit.
1070         //
1071         HttpResponder res = new HttpResponder();
1072         try
1073         {
1074             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1075             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1076             kpg.initialize(ecGenSpec, new SecureRandom());
1077             KeyPair enrollmentPair = kpg.generateKeyPair();
1078 
1079 
1080             TrustAnchor ta = new TrustAnchor(
1081                 ESTTestUtils.toJavaX509Certificate(
1082                     ESTTestUtils.readPemCertificate(
1083                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1084                     )
1085                 ), null);
1086 
1087 
1088             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1089                 new X500Name("CN=Test"),
1090                 enrollmentPair.getPublic());
1091 
1092             PKCS10CertificationRequest csr = pkcs10Builder.build(
1093                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1094 
1095             //
1096             // Even though we are using TLS we still need to use an HTTP auth.
1097             //
1098 
1099             int port = res.open(responseData.toByteArray());
1100 
1101 
1102             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1103                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1104                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1105                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1106                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1107 
1108 
1109             builder.addCipherSuites(res.getSupportedCipherSuites());
1110 
1111 
1112             try
1113             {
1114                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr, null);
1115                 Assert.fail("Must throw exception.");
1116             }
1117             catch (Exception t)
1118             {
1119                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1120                 Assert.assertEquals("", 400, ((ESTException)t).getStatusCode());
1121             }
1122 
1123         }
1124         catch (Exception ex)
1125         {
1126             ex.printStackTrace();
1127         }
1128         finally
1129         {
1130             res.close();
1131         }
1132 
1133         res.getFinished().await(5, TimeUnit.SECONDS);
1134 
1135     }
1136 
1137     @Test()
testResponseWith401BAndBadQOP()1138     public void testResponseWith401BAndBadQOP()
1139         throws Exception
1140     {
1141         ESTTestUtils.ensureProvider();
1142         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1143 
1144         PrintWriter pw = new PrintWriter(responseData);
1145         pw.print("HTTP/1.1 401 Unauthorized\n" +
1146             "Status: 401 Unauthorized\n" +
1147             "Content-Length: 0\n" +
1148             "WWW-Authenticate: Digest qop=\"invalid\", realm=\"estrealm\", nonce=\"1487704890\", algorithm=\"md5\"\n\n");
1149         pw.flush();
1150 
1151         //
1152         // Test content length enforcement.
1153         // Fail when content-length = read limit.
1154         //
1155         HttpResponder res = new HttpResponder();
1156         try
1157         {
1158             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1159             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1160             kpg.initialize(ecGenSpec, new SecureRandom());
1161             KeyPair enrollmentPair = kpg.generateKeyPair();
1162 
1163 
1164             TrustAnchor ta = new TrustAnchor(
1165                 ESTTestUtils.toJavaX509Certificate(
1166                     ESTTestUtils.readPemCertificate(
1167                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1168                     )
1169                 ), null);
1170 
1171 
1172             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1173                 new X500Name("CN=Test"),
1174                 enrollmentPair.getPublic());
1175 
1176             PKCS10CertificationRequest csr = pkcs10Builder.build(
1177                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1178 
1179             //
1180             // Even though we are using TLS we still need to use an HTTP auth.
1181             //
1182 
1183             int port = res.open(responseData.toByteArray());
1184 
1185 
1186             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1187                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1188                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1189                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1190                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1191 
1192 
1193             builder.addCipherSuites(res.getSupportedCipherSuites());
1194 
1195 
1196             try
1197             {
1198                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
1199                     new HttpAuth(
1200                         "estrealm",
1201                         "estuser",
1202                         "estpwd".toCharArray(),
1203                         new SecureRandom(),
1204                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
1205                 );
1206                 Assert.fail("Must throw exception.");
1207             }
1208             catch (Exception t)
1209             {
1210                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1211                 Assert.assertTrue("", t.getMessage().contains("QoP value unknown: '0'"));
1212             }
1213         }
1214         catch (Exception ex)
1215         {
1216             ex.printStackTrace();
1217         }
1218         finally
1219         {
1220             res.close();
1221         }
1222 
1223         res.getFinished().await(5, TimeUnit.SECONDS);
1224 
1225     }
1226 
1227     @Test()
testResponseWith401UknownValueInHeader()1228     public void testResponseWith401UknownValueInHeader()
1229         throws Exception
1230     {
1231         ESTTestUtils.ensureProvider();
1232         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1233 
1234         PrintWriter pw = new PrintWriter(responseData);
1235         pw.print("HTTP/1.1 401 Unauthorized\n" +
1236             "Status: 401 Unauthorized\n" +
1237             "Content-Length: 0\n" +
1238             "WWW-Authenticate: Digest qop=\"invalid\", realm=\"estrealm\", nonce=\"1487704890\", algorithm=\"md5\", dummy=\"value\"\n\n");
1239         pw.flush();
1240 
1241         //
1242         // Test content length enforcement.
1243         // Fail when content-length = read limit.
1244         //
1245         HttpResponder res = new HttpResponder();
1246         try
1247         {
1248             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1249             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1250             kpg.initialize(ecGenSpec, new SecureRandom());
1251             KeyPair enrollmentPair = kpg.generateKeyPair();
1252 
1253 
1254             TrustAnchor ta = new TrustAnchor(
1255                 ESTTestUtils.toJavaX509Certificate(
1256                     ESTTestUtils.readPemCertificate(
1257                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1258                     )
1259                 ), null);
1260 
1261 
1262             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1263                 new X500Name("CN=Test"),
1264                 enrollmentPair.getPublic());
1265 
1266             PKCS10CertificationRequest csr = pkcs10Builder.build(
1267                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1268 
1269             //
1270             // Even though we are using TLS we still need to use an HTTP auth.
1271             //
1272 
1273             int port = res.open(responseData.toByteArray());
1274 
1275 
1276             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1277                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1278                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1279                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1280                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1281 
1282             builder.addCipherSuites(res.getSupportedCipherSuites());
1283 
1284 
1285             try
1286             {
1287                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
1288                     new HttpAuth(
1289                         "estrealm",
1290                         "estuser",
1291                         "estpwd".toCharArray(),
1292                         new SecureRandom(),
1293                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
1294                 );
1295                 Assert.fail("Must throw exception.");
1296             }
1297             catch (Exception t)
1298             {
1299                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1300                 Assert.assertTrue("", t.getMessage().contains("'dummy'"));
1301             }
1302         }
1303         catch (Exception ex)
1304         {
1305             ex.printStackTrace();
1306         }
1307         finally
1308         {
1309             res.close();
1310         }
1311 
1312         res.getFinished().await(5, TimeUnit.SECONDS);
1313 
1314     }
1315 
1316 
1317     @Test()
testResponseWith401QpopEmpty()1318     public void testResponseWith401QpopEmpty()
1319         throws Exception
1320     {
1321         ESTTestUtils.ensureProvider();
1322         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1323 
1324         PrintWriter pw = new PrintWriter(responseData);
1325         pw.print("HTTP/1.1 401 Unauthorized\n" +
1326             "Status: 401 Unauthorized\n" +
1327             "Content-Length: 0\n" +
1328             "WWW-Authenticate: Digest qop=\"\", realm=\"estrealm\", nonce=\"1487704890\", algorithm=\"md5\"\n\n");
1329         pw.flush();
1330 
1331         //
1332         // Test content length enforcement.
1333         // Fail when content-length = read limit.
1334         //
1335         HttpResponder res = new HttpResponder();
1336         try
1337         {
1338             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1339             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1340             kpg.initialize(ecGenSpec, new SecureRandom());
1341             KeyPair enrollmentPair = kpg.generateKeyPair();
1342 
1343 
1344             TrustAnchor ta = new TrustAnchor(
1345                 ESTTestUtils.toJavaX509Certificate(
1346                     ESTTestUtils.readPemCertificate(
1347                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1348                     )
1349                 ), null);
1350 
1351 
1352             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1353                 new X500Name("CN=Test"),
1354                 enrollmentPair.getPublic());
1355 
1356             PKCS10CertificationRequest csr = pkcs10Builder.build(
1357                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1358 
1359             //
1360             // Even though we are using TLS we still need to use an HTTP auth.
1361             //
1362 
1363             int port = res.open(responseData.toByteArray());
1364 
1365 
1366             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1367                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1368                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1369                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1370                 )), null));
1371 
1372             builder.addCipherSuites(res.getSupportedCipherSuites());
1373             builder.withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1374 
1375 
1376             try
1377             {
1378                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
1379                     new HttpAuth(
1380                         "estrealm",
1381                         "estuser",
1382                         "estpwd".toCharArray(),
1383                         new SecureRandom(),
1384                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
1385                 );
1386                 Assert.fail("Must throw exception.");
1387             }
1388             catch (Exception t)
1389             {
1390                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1391                 Assert.assertTrue("", t.getMessage().contains("value is empty"));
1392             }
1393         }
1394         catch (Exception ex)
1395         {
1396             ex.printStackTrace();
1397         }
1398         finally
1399         {
1400             res.close();
1401         }
1402 
1403         res.getFinished().await(5, TimeUnit.SECONDS);
1404 
1405     }
1406 
1407 
1408     @Test()
testResponseWith401BadMode()1409     public void testResponseWith401BadMode()
1410         throws Exception
1411     {
1412         ESTTestUtils.ensureProvider();
1413         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1414 
1415         PrintWriter pw = new PrintWriter(responseData);
1416         pw.print("HTTP/1.1 401 Unauthorized\n" +
1417             "Status: 401 Unauthorized\n" +
1418             "Content-Length: 0\n" +
1419             "WWW-Authenticate: Banana qop=\"\", realm=\"estrealm\", nonce=\"1487704890\", algorithm=\"md5\"\n\n");
1420         pw.flush();
1421 
1422         //
1423         // Test content length enforcement.
1424         // Fail when content-length = read limit.
1425         //
1426         HttpResponder res = new HttpResponder();
1427         try
1428         {
1429             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1430             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1431             kpg.initialize(ecGenSpec, new SecureRandom());
1432             KeyPair enrollmentPair = kpg.generateKeyPair();
1433 
1434 
1435             TrustAnchor ta = new TrustAnchor(
1436                 ESTTestUtils.toJavaX509Certificate(
1437                     ESTTestUtils.readPemCertificate(
1438                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1439                     )
1440                 ), null);
1441 
1442 
1443             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1444                 new X500Name("CN=Test"),
1445                 enrollmentPair.getPublic());
1446 
1447             PKCS10CertificationRequest csr = pkcs10Builder.build(
1448                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1449 
1450             //
1451             // Even though we are using TLS we still need to use an HTTP auth.
1452             //
1453 
1454             int port = res.open(responseData.toByteArray());
1455 
1456 
1457             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1458                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1459                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1460                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1461                 )), null));
1462 
1463             builder.withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1464 
1465             builder.addCipherSuites(res.getSupportedCipherSuites());
1466 
1467 
1468             try
1469             {
1470                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
1471                     new HttpAuth(
1472                         "estrealm",
1473                         "estuser",
1474                         "estpwd".toCharArray(),
1475                         new SecureRandom(),
1476                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
1477                 );
1478                 Assert.fail("Must throw exception.");
1479             }
1480             catch (Exception t)
1481             {
1482                 t.printStackTrace();
1483                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1484                 Assert.assertTrue("", t.getMessage().contains("banana"));
1485             }
1486         }
1487         catch (Exception ex)
1488         {
1489             ex.printStackTrace();
1490         }
1491         finally
1492         {
1493             res.close();
1494         }
1495 
1496         res.getFinished().await(5, TimeUnit.SECONDS);
1497 
1498     }
1499 
1500 
1501     @Test()
testResponseWith401AndNoWWWHeader()1502     public void testResponseWith401AndNoWWWHeader()
1503         throws Exception
1504     {
1505         ESTTestUtils.ensureProvider();
1506         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1507 
1508         PrintWriter pw = new PrintWriter(responseData);
1509         pw.print("HTTP/1.1 401 Unauthorized\n" +
1510             "Status: 401 Unauthorized\n" +
1511             "Content-Length: 0\n" +
1512             "\n");
1513         pw.flush();
1514 
1515         //
1516         // Test content length enforcement.
1517         // Fail when content-length = read limit.
1518         //
1519         HttpResponder res = new HttpResponder();
1520         try
1521         {
1522             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1523             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1524             kpg.initialize(ecGenSpec, new SecureRandom());
1525             KeyPair enrollmentPair = kpg.generateKeyPair();
1526 
1527 
1528             TrustAnchor ta = new TrustAnchor(
1529                 ESTTestUtils.toJavaX509Certificate(
1530                     ESTTestUtils.readPemCertificate(
1531                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1532                     )
1533                 ), null);
1534 
1535 
1536             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1537                 new X500Name("CN=Test"),
1538                 enrollmentPair.getPublic());
1539 
1540             PKCS10CertificationRequest csr = pkcs10Builder.build(
1541                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1542 
1543             //
1544             // Even though we are using TLS we still need to use an HTTP auth.
1545             //
1546 
1547             int port = res.open(responseData.toByteArray());
1548 
1549 
1550             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1551                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1552                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1553                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1554                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1555 
1556 
1557             builder.addCipherSuites(res.getSupportedCipherSuites());
1558 
1559 
1560             try
1561             {
1562                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
1563                     new HttpAuth(
1564                         "estrealm",
1565                         "estuser",
1566                         "estpwd".toCharArray(),
1567                         new SecureRandom(),
1568                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
1569                 );
1570                 Assert.fail("Must throw exception.");
1571             }
1572             catch (Exception t)
1573             {
1574                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1575                 Assert.assertTrue("", t.getMessage().contains("no WWW-Authenticate"));
1576             }
1577         }
1578         catch (Exception ex)
1579         {
1580             ex.printStackTrace();
1581         }
1582         finally
1583         {
1584             res.close();
1585         }
1586 
1587         res.getFinished().await(5, TimeUnit.SECONDS);
1588 
1589     }
1590 
1591 
1592       @Test()
testResponseWith401AndBadAlgorithm()1593     public void testResponseWith401AndBadAlgorithm()
1594         throws Exception
1595     {
1596         ESTTestUtils.ensureProvider();
1597         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1598 
1599         PrintWriter pw = new PrintWriter(responseData);
1600         pw.print("HTTP/1.1 401 Unauthorized\n" +
1601             "Status: 401 Unauthorized\n" +
1602             "Content-Length: 0\n" +
1603             "WWW-Authenticate: Digest qop=\"auth\", realm=\"estrealm\", nonce=\"1487706836\", algorithm=\"token\"\n\n");
1604         pw.flush();
1605 
1606         //
1607         // Test content length enforcement.
1608         // Fail when content-length = read limit.
1609         //
1610         HttpResponder res = new HttpResponder();
1611         try
1612         {
1613             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1614             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1615             kpg.initialize(ecGenSpec, new SecureRandom());
1616             KeyPair enrollmentPair = kpg.generateKeyPair();
1617 
1618 
1619             TrustAnchor ta = new TrustAnchor(
1620                 ESTTestUtils.toJavaX509Certificate(
1621                     ESTTestUtils.readPemCertificate(
1622                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1623                     )
1624                 ), null);
1625 
1626 
1627             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1628                 new X500Name("CN=Test"),
1629                 enrollmentPair.getPublic());
1630 
1631             PKCS10CertificationRequest csr = pkcs10Builder.build(
1632                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1633 
1634             //
1635             // Even though we are using TLS we still need to use an HTTP auth.
1636             //
1637 
1638             int port = res.open(responseData.toByteArray());
1639 
1640 
1641             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1642                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1643                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1644                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1645                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1646 
1647 
1648             builder.addCipherSuites(res.getSupportedCipherSuites());
1649 
1650 
1651             try
1652             {
1653                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
1654                     new HttpAuth(
1655                         "estrealm",
1656                         "estuser",
1657                         "estpwd".toCharArray(),
1658                         new SecureRandom(),
1659                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
1660                 );
1661                 Assert.fail("Must throw exception.");
1662             }
1663             catch (Exception t)
1664             {
1665                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1666                 Assert.assertTrue("", t.getMessage().contains("digest algorithm unknown"));
1667             }
1668         }
1669         catch (Exception ex)
1670         {
1671             ex.printStackTrace();
1672         }
1673         finally
1674         {
1675             res.close();
1676         }
1677 
1678         res.getFinished().await(5, TimeUnit.SECONDS);
1679 
1680     }
1681 
1682 
1683     @Test()
testResponseWith401AndEmptyAlgorithm()1684     public void testResponseWith401AndEmptyAlgorithm()
1685         throws Exception
1686     {
1687         ESTTestUtils.ensureProvider();
1688         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1689 
1690         PrintWriter pw = new PrintWriter(responseData);
1691         pw.print("HTTP/1.1 401 Unauthorized\n" +
1692             "Status: 401 Unauthorized\n" +
1693             "Content-Length: 0\n" +
1694             "WWW-Authenticate: Digest qop=\"auth\", realm=\"estrealm\", nonce=\"1487706836\", algorithm=\"\"\n\n");
1695         pw.flush();
1696 
1697         //
1698         // Test content length enforcement.
1699         // Fail when content-length = read limit.
1700         //
1701         HttpResponder res = new HttpResponder();
1702         try
1703         {
1704             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1705             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1706             kpg.initialize(ecGenSpec, new SecureRandom());
1707             KeyPair enrollmentPair = kpg.generateKeyPair();
1708 
1709 
1710             TrustAnchor ta = new TrustAnchor(
1711                 ESTTestUtils.toJavaX509Certificate(
1712                     ESTTestUtils.readPemCertificate(
1713                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1714                     )
1715                 ), null);
1716 
1717 
1718             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1719                 new X500Name("CN=Test"),
1720                 enrollmentPair.getPublic());
1721 
1722             PKCS10CertificationRequest csr = pkcs10Builder.build(
1723                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1724 
1725             //
1726             // Even though we are using TLS we still need to use an HTTP auth.
1727             //
1728 
1729             int port = res.open(responseData.toByteArray());
1730 
1731 
1732             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1733                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1734                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1735                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1736                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1737 
1738 
1739             builder.addCipherSuites(res.getSupportedCipherSuites());
1740 
1741 
1742             try
1743             {
1744                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
1745                     new HttpAuth(
1746                         "estrealm",
1747                         "estuser",
1748                         "estpwd".toCharArray(),
1749                         new SecureRandom(),
1750                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
1751                 );
1752                 Assert.fail("Must throw exception.");
1753             }
1754             catch (Exception t)
1755             {
1756                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1757                 Assert.assertTrue("", t.getMessage().contains("no algorithm defined"));
1758             }
1759         }
1760         catch (Exception ex)
1761         {
1762             ex.printStackTrace();
1763         }
1764         finally
1765         {
1766             res.close();
1767         }
1768 
1769         res.getFinished().await(5, TimeUnit.SECONDS);
1770 
1771     }
1772 
1773 
1774 
1775 
1776 
1777     @Test()
testResponseWith401NullNonce()1778     public void testResponseWith401NullNonce()
1779         throws Exception
1780     {
1781         ESTTestUtils.ensureProvider();
1782         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1783 
1784         PrintWriter pw = new PrintWriter(responseData);
1785         pw.print("HTTP/1.1 401 Unauthorized\n" +
1786             "Status: 401 Unauthorized\n" +
1787             "Content-Length: 0\n" +
1788             "WWW-Authenticate: Digest qop=\"auth\", realm=\"estrealm\", nonce=\n\n");
1789         pw.flush();
1790 
1791         //
1792         // Test content length enforcement.
1793         // Fail when content-length = read limit.
1794         //
1795         HttpResponder res = new HttpResponder();
1796         try
1797         {
1798             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1799             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1800             kpg.initialize(ecGenSpec, new SecureRandom());
1801             KeyPair enrollmentPair = kpg.generateKeyPair();
1802 
1803 
1804             TrustAnchor ta = new TrustAnchor(
1805                 ESTTestUtils.toJavaX509Certificate(
1806                     ESTTestUtils.readPemCertificate(
1807                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1808                     )
1809                 ), null);
1810 
1811 
1812             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1813                 new X500Name("CN=Test"),
1814                 enrollmentPair.getPublic());
1815 
1816             PKCS10CertificationRequest csr = pkcs10Builder.build(
1817                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1818 
1819             //
1820             // Even though we are using TLS we still need to use an HTTP auth.
1821             //
1822 
1823             int port = res.open(responseData.toByteArray());
1824 
1825 
1826             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1827                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1828                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1829                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1830                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1831 
1832             builder.addCipherSuites(res.getSupportedCipherSuites());
1833 
1834 
1835             try
1836             {
1837                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
1838                     new HttpAuth(
1839                         "estrealm",
1840                         "estuser",
1841                         "estpwd".toCharArray(),
1842                         new SecureRandom(),
1843                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
1844                 );
1845                 Assert.fail("Must throw exception.");
1846             }
1847             catch (Exception t)
1848             {
1849                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1850                 Assert.assertTrue("", t.getMessage().contains("Expecting start quote"));
1851             }
1852         }
1853         catch (Exception ex)
1854         {
1855             ex.printStackTrace();
1856         }
1857         finally
1858         {
1859             res.close();
1860         }
1861 
1862         res.getFinished().await(5, TimeUnit.SECONDS);
1863 
1864     }
1865 
1866 
1867     @Test()
testResponseWith401NullRealm()1868     public void testResponseWith401NullRealm()
1869         throws Exception
1870     {
1871         ESTTestUtils.ensureProvider();
1872         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1873 
1874         PrintWriter pw = new PrintWriter(responseData);
1875         pw.print("HTTP/1.1 401 Unauthorized\n" +
1876             "Status: 401 Unauthorized\n" +
1877             "Content-Length: 0\n" +
1878             "WWW-Authenticate: Digest qop=\"auth\", realm=, nonce=\"1234\"\n\n");
1879         pw.flush();
1880 
1881         //
1882         // Test content length enforcement.
1883         // Fail when content-length = read limit.
1884         //
1885         HttpResponder res = new HttpResponder();
1886         try
1887         {
1888             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1889             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1890             kpg.initialize(ecGenSpec, new SecureRandom());
1891             KeyPair enrollmentPair = kpg.generateKeyPair();
1892 
1893 
1894             TrustAnchor ta = new TrustAnchor(
1895                 ESTTestUtils.toJavaX509Certificate(
1896                     ESTTestUtils.readPemCertificate(
1897                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1898                     )
1899                 ), null);
1900 
1901 
1902             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1903                 new X500Name("CN=Test"),
1904                 enrollmentPair.getPublic());
1905 
1906             PKCS10CertificationRequest csr = pkcs10Builder.build(
1907                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1908 
1909             //
1910             // Even though we are using TLS we still need to use an HTTP auth.
1911             //
1912 
1913             int port = res.open(responseData.toByteArray());
1914 
1915             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
1916                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
1917                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
1918                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1919                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
1920 
1921             builder.addCipherSuites(res.getSupportedCipherSuites());
1922 
1923 
1924             try
1925             {
1926                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
1927                     new HttpAuth(
1928                         "estrealm",
1929                         "estuser",
1930                         "estpwd".toCharArray(),
1931                         new SecureRandom(),
1932                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
1933                 );
1934                 Assert.fail("Must throw exception.");
1935             }
1936             catch (Exception t)
1937             {
1938                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
1939                 Assert.assertTrue("", t.getMessage().contains("Expecting start quote"));
1940             }
1941         }
1942         catch (Exception ex)
1943         {
1944             ex.printStackTrace();
1945         }
1946         finally
1947         {
1948             res.close();
1949         }
1950 
1951         res.getFinished().await(5, TimeUnit.SECONDS);
1952 
1953     }
1954 
1955 
1956     @Test()
testResponseWith401NullQop()1957     public void testResponseWith401NullQop()
1958         throws Exception
1959     {
1960         ESTTestUtils.ensureProvider();
1961         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
1962 
1963         PrintWriter pw = new PrintWriter(responseData);
1964         pw.print("HTTP/1.1 401 Unauthorized\n" +
1965             "Status: 401 Unauthorized\n" +
1966             "Content-Length: 0\n" +
1967             "WWW-Authenticate: Digest realm=\"estrealm\", nonce=\"1487778654\", qop=\n\n");
1968         pw.flush();
1969 
1970         //
1971         // Test content length enforcement.
1972         // Fail when content-length = read limit.
1973         //
1974         HttpResponder res = new HttpResponder();
1975         try
1976         {
1977             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
1978             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
1979             kpg.initialize(ecGenSpec, new SecureRandom());
1980             KeyPair enrollmentPair = kpg.generateKeyPair();
1981 
1982 
1983             TrustAnchor ta = new TrustAnchor(
1984                 ESTTestUtils.toJavaX509Certificate(
1985                     ESTTestUtils.readPemCertificate(
1986                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
1987                     )
1988                 ), null);
1989 
1990 
1991             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
1992                 new X500Name("CN=Test"),
1993                 enrollmentPair.getPublic());
1994 
1995             PKCS10CertificationRequest csr = pkcs10Builder.build(
1996                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
1997 
1998             //
1999             // Even though we are using TLS we still need to use an HTTP auth.
2000             //
2001 
2002             int port = res.open(responseData.toByteArray());
2003 
2004 
2005             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
2006                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
2007                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
2008                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
2009                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
2010 
2011 
2012             builder.addCipherSuites(res.getSupportedCipherSuites());
2013 
2014 
2015             try
2016             {
2017                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
2018                     new HttpAuth(
2019                         "estrealm",
2020                         "estuser",
2021                         "estpwd".toCharArray(),
2022                         new SecureRandom(),
2023                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
2024                 );
2025                 Assert.fail("Must throw exception.");
2026             }
2027             catch (Exception t)
2028             {
2029                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
2030                 Assert.assertTrue("", t.getMessage().contains("Expecting start quote"));
2031             }
2032         }
2033         catch (Exception ex)
2034         {
2035             ex.printStackTrace();
2036         }
2037         finally
2038         {
2039             res.close();
2040         }
2041 
2042         res.getFinished().await(5, TimeUnit.SECONDS);
2043 
2044     }
2045 
2046 
2047     @Test()
testResponseWith202NoRetryHeader()2048     public void testResponseWith202NoRetryHeader()
2049         throws Exception
2050     {
2051         ESTTestUtils.ensureProvider();
2052         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
2053 
2054         PrintWriter pw = new PrintWriter(responseData);
2055         pw.print("HTTP/1.1 202 Accepted\n" +
2056             "Status: 202 Accepted\n" +
2057             "Content-Length: 0\n\n");
2058         pw.flush();
2059 
2060         //
2061         // Test content length enforcement.
2062         // Fail when content-length = read limit.
2063         //
2064         HttpResponder res = new HttpResponder();
2065         try
2066         {
2067             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
2068             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
2069             kpg.initialize(ecGenSpec, new SecureRandom());
2070             KeyPair enrollmentPair = kpg.generateKeyPair();
2071 
2072 
2073             TrustAnchor ta = new TrustAnchor(
2074                 ESTTestUtils.toJavaX509Certificate(
2075                     ESTTestUtils.readPemCertificate(
2076                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
2077                     )
2078                 ), null);
2079 
2080 
2081             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
2082                 new X500Name("CN=Test"),
2083                 enrollmentPair.getPublic());
2084 
2085             PKCS10CertificationRequest csr = pkcs10Builder.build(
2086                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
2087 
2088             //
2089             // Even though we are using TLS we still need to use an HTTP auth.
2090             //
2091 
2092             int port = res.open(responseData.toByteArray());
2093 
2094 
2095             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
2096                 "localhost:" + port, JcaJceUtils.getCertPathTrustManager(
2097                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
2098                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
2099                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
2100 
2101             builder.addCipherSuites(res.getSupportedCipherSuites());
2102 
2103 
2104             try
2105             {
2106                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
2107                     new HttpAuth(
2108                         "estrealm",
2109                         "estuser",
2110                         "estpwd".toCharArray(),
2111                         new SecureRandom(),
2112                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
2113                 );
2114                 Assert.fail("Must throw exception.");
2115             }
2116             catch (Exception t)
2117             {
2118                 Assert.assertEquals("Must be ESTException", t.getClass(), ESTException.class);
2119                 Assert.assertTrue("", t.getMessage().contains("not Retry-After header"));
2120             }
2121         }
2122         catch (Exception ex)
2123         {
2124             ex.printStackTrace();
2125         }
2126         finally
2127         {
2128             res.close();
2129         }
2130 
2131         res.getFinished().await(5, TimeUnit.SECONDS);
2132 
2133     }
2134 
2135 
2136     @Test()
testWithLabel()2137     public void testWithLabel()
2138         throws Exception
2139     {
2140         ESTTestUtils.ensureProvider();
2141         final ByteArrayOutputStream responseData = new ByteArrayOutputStream();
2142 
2143         PrintWriter pw = new PrintWriter(responseData);
2144         pw.print("HTTP/1.1 202 Accepted\n" +
2145             "Status: 202 Accepted\n" +
2146             "Content-Length: 0\n\n");
2147         pw.flush();
2148 
2149         //
2150         // Test content length enforcement.
2151         // Fail when content-length = read limit.
2152         //
2153 
2154         ArrayList<String> lines = new ArrayList<String>();
2155 
2156         HttpResponder res = new HttpResponder(lines);
2157         try
2158         {
2159             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
2160             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
2161             kpg.initialize(ecGenSpec, new SecureRandom());
2162             KeyPair enrollmentPair = kpg.generateKeyPair();
2163 
2164 
2165             TrustAnchor ta = new TrustAnchor(
2166                 ESTTestUtils.toJavaX509Certificate(
2167                     ESTTestUtils.readPemCertificate(
2168                         ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
2169                     )
2170                 ), null);
2171 
2172 
2173             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
2174                 new X500Name("CN=Test"),
2175                 enrollmentPair.getPublic());
2176 
2177             PKCS10CertificationRequest csr = pkcs10Builder.build(
2178                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
2179 
2180             //
2181             // Even though we are using TLS we still need to use an HTTP auth.
2182             //
2183 
2184             int port = res.open(responseData.toByteArray());
2185 
2186 
2187             JsseESTServiceBuilder builder = new JsseESTServiceBuilder(
2188                 "localhost:" + port , JcaJceUtils.getCertPathTrustManager(
2189                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificate(
2190                     ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
2191                 )), null)).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS");
2192 
2193             builder.addCipherSuites(res.getSupportedCipherSuites());
2194             builder.withLabel("the_label");
2195 
2196             /*
2197                 We are only checking the use of the label.
2198              */
2199 
2200 
2201             try
2202             {
2203                 EnrollmentResponse resp = builder.build().simpleEnroll(false, csr,
2204                     new HttpAuth(
2205                         "estrealm",
2206                         "estuser",
2207                         "estpwd".toCharArray(),
2208                         new SecureRandom(),
2209                         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
2210                 );
2211                 Assert.fail("Must throw exception.");
2212             }
2213             catch (Exception t)
2214             {
2215 //                  // Not tested here, tested elsewhere.
2216             }
2217 
2218             Assert.assertTrue(lines.get(0).contains("/.well-known/est/the_label/simpleenroll"));
2219 
2220 
2221         }
2222         catch (Exception ex)
2223         {
2224             ex.printStackTrace();
2225         }
2226         finally
2227         {
2228             res.close();
2229         }
2230 
2231         res.getFinished().await(5, TimeUnit.SECONDS);
2232 
2233     }
2234 
2235 
2236     @Test
testEnrollUsingBasicAuthWrongUsage()2237     public void testEnrollUsingBasicAuthWrongUsage()
2238         throws Exception
2239     {
2240         ESTTestUtils.ensureProvider();
2241         X509CertificateHolder[] theirCAs = null;
2242         ESTServerUtils.ServerInstance serverInstance = null;
2243 
2244         try
2245         {
2246             serverInstance = startDefaultServerTLSAndBasicAuthSpecial(0, false);
2247 
2248 
2249             ESTService est = new JsseESTServiceBuilder(
2250                 "localhost:8443", JcaJceUtils.getCertPathTrustManager(
2251                 ESTTestUtils.toTrustAnchor(ESTTestUtils.readPemCertificates(
2252                     ESTServerUtils.makeRelativeToServerHome("/estCA/multicacerts.crt")
2253                 )), null)
2254             ).withProvider(BouncyCastleJsseProvider.PROVIDER_NAME).withTLSVersion("TLS").build();
2255 
2256 
2257             //
2258             // Make certificate request.
2259             //
2260 
2261             ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
2262             KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC");
2263             kpg.initialize(ecGenSpec, new SecureRandom());
2264             KeyPair enrollmentPair = kpg.generateKeyPair();
2265 
2266             PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(
2267                 new X500Name("CN=Test"),
2268                 enrollmentPair.getPublic());
2269 
2270             PKCS10CertificationRequest csr = pkcs10Builder.build(
2271                 new JcaContentSignerBuilder("SHA256WITHECDSA").setProvider("BC").build(enrollmentPair.getPrivate()));
2272 
2273             EnrollmentResponse enr = est.simpleEnroll(false, csr,
2274                 new JcaHttpAuthBuilder("estreal", "estuser", "estpwd".toCharArray())
2275                     .setNonceGenerator(new SecureRandom()).setProvider("BC").build());
2276             X509Certificate expectedCA = ESTTestUtils.toJavaX509Certificate(ESTTestUtils.readPemCertificate(
2277                 ESTServerUtils.makeRelativeToServerHome("/estCA/cacert.crt")
2278             ));
2279 
2280             X509CertificateHolder enrolledAsHolder = ESTService.storeToArray(enr.getStore())[0];
2281 
2282             X509Certificate enrolled = ESTTestUtils.toJavaX509Certificate(enrolledAsHolder);
2283 
2284             // Will fail if it does not verify.
2285             enrolled.verify(expectedCA.getPublicKey(), "BC");
2286 
2287 
2288         } catch (Throwable t) {
2289             //
2290             // Non-ideal for testing but the TLS library emits errors that can not accidentally be printed to
2291             // a web page and aid an attacker.
2292             //
2293             Assert.assertTrue(t.getMessage().toLowerCase().contains("certificate_unknown"));
2294         }
2295         finally
2296         {
2297             if (serverInstance != null)
2298             {
2299                 serverInstance.getServer().stop_server();
2300             }
2301         }
2302     }
2303 
2304 
2305 
main(String[] args)2306     public static void main(String[] args)
2307         throws Exception
2308     {
2309 
2310 ////        Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
2311 ////
2312 ////        c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[16], "AES"), new GCMParameterSpec(32, new byte[16]));
2313 //        Security.addProvider(new BouncyCastleProvider());
2314 //        for (Iterator it = Security.getProvider("BC").getServices().iterator(); it.hasNext();)
2315 //        {
2316 //            Provider.Service s = (Provider.Service)it.next();
2317 //
2318 //            if (s.getAlgorithm().equals("AES"))
2319 //            {
2320 //                System.err.println(s.getAttribute("SupportedKeyFormats"));
2321 //            }
2322 //        }
2323 
2324         ESTTestUtils.ensureProvider();
2325         runTest(new TestEnroll());
2326     }
2327 
2328 }
2329