From 0fa454c645aace5da1a5a9ec72729d6a976d2ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vesa=20J=C3=A4=C3=A4skel=C3=A4inen?= Date: Sun, 27 Sep 2020 14:03:06 +0300 Subject: [PATCH] SecurityTest: Add certificate usage unit tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Vesa Jääskeläinen Also-by : Simon Bernard --- .../leshan/client/californium/X509Util.java | 20 + .../tests/SecureIntegrationTestHelper.java | 71 +- .../integration/tests/SecurityTest.java | 892 ++++++++++++++++++ 3 files changed, 981 insertions(+), 2 deletions(-) diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/X509Util.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/X509Util.java index 7c207dc68a..afe6663676 100644 --- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/X509Util.java +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/X509Util.java @@ -19,11 +19,14 @@ import java.security.cert.CertPath; import java.security.cert.CertPathValidator; import java.security.cert.CertPathValidatorResult; +import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; import java.security.cert.PKIXCertPathValidatorResult; import java.security.cert.PKIXParameters; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -122,4 +125,21 @@ public static boolean contains(X509Certificate certificate, X509Certificate[] ce } return false; } + + /** + * Convert array of {@link Certificate} to array of {@link X509Certificate} + */ + public static X509Certificate[] asX509Certificates(Certificate[] certificates) throws CertificateException { + ArrayList x509Certificates = new ArrayList<>(); + + for (Certificate cert : certificates) { + if (!(cert instanceof X509Certificate)) { + throw new CertificateException(String.format( + "%s certificate format is not supported, Only X.509 certificate is supported", cert.getType())); + } + x509Certificates.add((X509Certificate) cert); + } + + return x509Certificates.toArray(new X509Certificate[0]); + } } diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java index 34537b7295..296f639b83 100644 --- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java +++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java @@ -37,6 +37,8 @@ import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPublicKeySpec; import java.security.spec.KeySpec; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javax.crypto.SecretKey; @@ -53,6 +55,7 @@ import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; import org.eclipse.californium.scandium.dtls.pskstore.AdvancedPskStore; import org.eclipse.leshan.client.californium.LeshanClientBuilder; +import org.eclipse.leshan.client.californium.X509Util; import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory; import org.eclipse.leshan.client.object.Device; import org.eclipse.leshan.client.object.Security; @@ -60,6 +63,7 @@ import org.eclipse.leshan.client.resource.DummyInstanceEnabler; import org.eclipse.leshan.client.resource.LwM2mObjectEnabler; import org.eclipse.leshan.client.resource.ObjectsInitializer; +import org.eclipse.leshan.core.CertificateUsage; import org.eclipse.leshan.core.LwM2mId; import org.eclipse.leshan.core.californium.EndpointFactory; import org.eclipse.leshan.core.util.Hex; @@ -89,8 +93,12 @@ public class SecureIntegrationTestHelper extends IntegrationTestHelper { // client private key used for X509 public final PrivateKey clientPrivateKeyFromCert; + // mfg client private key used for X509 + public final PrivateKey mfgClientPrivateKeyFromCert; // server private key used for X509 public final PrivateKey serverPrivateKeyFromCert; + // server private key used for X509 + public final PrivateKey serverIntPrivateKeyFromCert; // client certificate signed by rootCA with a good CN (CN start by leshan_integration_test) public final X509Certificate clientX509Cert; // client certificate signed by rootCA but with bad CN (CN does not start by leshan_integration_test) @@ -99,14 +107,25 @@ public class SecureIntegrationTestHelper extends IntegrationTestHelper { public final X509Certificate clientX509CertSelfSigned; // client certificate signed by another CA (not rootCA) with a good CN (CN start by leshan_integration_test) public final X509Certificate clientX509CertNotTrusted; + // client certificate signed by manufacturer CA's with a good CN + // (CN=urn:dev:ops:32473-IoT_Device-K1234567,O=Manufacturer) + public final X509Certificate[] mfgClientX509CertChain; // server certificate signed by rootCA public final X509Certificate serverX509Cert; + // server certificate signed by intermediateCA + public final X509Certificate[] serverIntX509CertChain; // self-signed server certificate public final X509Certificate serverX509CertSelfSigned; + // self-signed server certificate + public final X509Certificate serverIntX509CertSelfSigned; // rootCA used by the server public final X509Certificate rootCAX509Cert; // certificates trustedby the server (should contain rootCA) public final Certificate[] trustedCertificates = new Certificate[1]; + // client's initial trust store + public final List clientTrustStore; + // client's initial empty trust store + public final List clientEmptyTrustStore = new ArrayList<>(); public SecureIntegrationTestHelper() { // create client credentials @@ -145,6 +164,9 @@ public SecureIntegrationTestHelper() { clientX509CertWithBadCN = (X509Certificate) clientKeyStore.getCertificate("client_bad_cn"); clientX509CertSelfSigned = (X509Certificate) clientKeyStore.getCertificate("client_self_signed"); clientX509CertNotTrusted = (X509Certificate) clientKeyStore.getCertificate("client_not_trusted"); + + mfgClientPrivateKeyFromCert = (PrivateKey) clientKeyStore.getKey("mfgClient", clientKeyStorePwd); + mfgClientX509CertChain = X509Util.asX509Certificates(clientKeyStore.getCertificateChain("mfgClient")); } catch (GeneralSecurityException | IOException e) { throw new RuntimeException(e); } @@ -181,11 +203,14 @@ public SecureIntegrationTestHelper() { } serverPrivateKeyFromCert = (PrivateKey) serverKeyStore.getKey("server", serverKeyStorePwd); + serverIntPrivateKeyFromCert = (PrivateKey) serverKeyStore.getKey("serverint", serverKeyStorePwd); rootCAX509Cert = (X509Certificate) serverKeyStore.getCertificate("rootCA"); serverX509Cert = (X509Certificate) serverKeyStore.getCertificate("server"); serverX509CertSelfSigned = (X509Certificate) serverKeyStore.getCertificate("server_self_signed"); + serverIntX509CertSelfSigned = (X509Certificate) serverKeyStore.getCertificate("serverInt_self_signed"); + serverIntX509CertChain = X509Util.asX509Certificates(serverKeyStore.getCertificateChain("serverint")); trustedCertificates[0] = rootCAX509Cert; - + clientTrustStore = Arrays.asList(new Certificate[] { rootCAX509Cert }); } catch (GeneralSecurityException | IOException e) { throw new RuntimeException(e); } @@ -333,6 +358,38 @@ public void createX509CertClient(Certificate clientCertificate, PrivateKey priva setupClientMonitoring(); } + public void createX509CertClient(X509Certificate[] clientCertificate, PrivateKey privatekey, + List clientTrustStore, X509Certificate serverCertificate, CertificateUsage certificateUsage) + throws CertificateEncodingException { + /* Make sure there is only 1 certificate in chain before client certificate chains are supported */ + assert (clientCertificate.length == 1); + + ObjectsInitializer initializer = new ObjectsInitializer(); + initializer.setInstancesForObject(LwM2mId.SECURITY, + Security.x509( + "coaps://" + server.getSecuredAddress().getHostString() + ":" + + server.getSecuredAddress().getPort(), + 12345, clientCertificate[0].getEncoded(), privatekey.getEncoded(), + serverCertificate.getEncoded(), certificateUsage.code)); + initializer.setInstancesForObject(LwM2mId.SERVER, new Server(12345, LIFETIME)); + initializer.setInstancesForObject(LwM2mId.DEVICE, new Device("Eclipse Leshan", MODEL_NUMBER, "12345")); + initializer.setClassForObject(LwM2mId.ACCESS_CONTROL, DummyInstanceEnabler.class); + List objects = initializer.createAll(); + + InetSocketAddress clientAddress = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); + LeshanClientBuilder builder = new LeshanClientBuilder(getCurrentEndpoint()); + builder.setLocalAddress(clientAddress.getHostString(), clientAddress.getPort()); + builder.setTrustStore(clientTrustStore); + + Builder dtlsConfig = new DtlsConnectorConfig.Builder(); + dtlsConfig.setClientOnly(); + builder.setDtlsConfig(dtlsConfig); + + builder.setObjects(objects); + client = builder.build(); + setupClientMonitoring(); + } + @Override protected LeshanServerBuilder createServerBuilder() { return createServerBuilder(null); @@ -367,9 +424,19 @@ public void createServerWithX509Cert() { } public void createServerWithX509Cert(X509Certificate serverCertificate, PrivateKey privateKey, Boolean serverOnly) { + createServerWithX509Cert(new X509Certificate[] { serverCertificate }, privateKey, serverOnly); + } + + public void createServerWithX509Cert(X509Certificate serverCertificateChain[], PrivateKey privateKey, + Boolean serverOnly) { + createServerWithX509Cert(serverCertificateChain, privateKey, this.trustedCertificates, serverOnly); + } + + public void createServerWithX509Cert(X509Certificate serverCertificateChain[], PrivateKey privateKey, + Certificate[] trustedCertificates, Boolean serverOnly) { LeshanServerBuilder builder = createServerBuilder(serverOnly); builder.setPrivateKey(privateKey); - builder.setCertificateChain(new X509Certificate[] { serverCertificate }); + builder.setCertificateChain(serverCertificateChain); builder.setTrustedCertificates(trustedCertificates); builder.setAuthorizer(new DefaultAuthorizer(securityStore, new SecurityChecker() { @Override diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecurityTest.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecurityTest.java index d8d6969353..2c50b6ccf7 100644 --- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecurityTest.java +++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecurityTest.java @@ -23,6 +23,7 @@ import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; import org.eclipse.californium.core.coap.CoAP.Type; import org.eclipse.californium.core.coap.Request; @@ -38,6 +39,7 @@ import org.eclipse.californium.elements.util.SimpleMessageCallback; import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.dtls.DTLSSession; +import org.eclipse.leshan.core.CertificateUsage; import org.eclipse.leshan.core.request.ReadRequest; import org.eclipse.leshan.core.request.exception.SendFailedException; import org.eclipse.leshan.core.request.exception.TimeoutException; @@ -692,6 +694,896 @@ public void registered_device_with_selfsigned_x509cert_to_server_with_x509cert() helper.ensureNoRegistration(1); } + /* ---- CA_CONSTRAINT ---- */ + + /** + *
+     * Test scenario:
+     * - Certificate Usage = CA constraint
+     * - Server Certificate = server certificate
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection  (direct trust is not allowed with "CA constraint" usage)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_ca() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[0], CertificateUsage.CA_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = CA constraint
+     * - Server Certificate = intermediate CA certificate
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client is able to connect (intermediate CA cert is part of the chain)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_ca_intca_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[1], CertificateUsage.CA_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.waitForRegistrationAtServerSide(1); + + assertNotNull(helper.getCurrentRegistration()); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = CA constraint
+     * - Server Certificate = root CA certificate (not end-entity certificate)
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client is able to connect (root CA cert is part of the chain)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_ca_domain_root_ca_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.rootCAX509Cert, CertificateUsage.CA_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.waitForRegistrationAtServerSide(1); + + assertNotNull(helper.getCurrentRegistration()); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = CA constraint
+     * - Server Certificate = other end-entity certificate with same dns name signed by same root ca
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_ca_other_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverX509Cert, CertificateUsage.CA_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = CA constraint
+     * - Server Certificate = self signed certificate given
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_ca_selfsigned_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertSelfSigned, CertificateUsage.CA_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = CA constraint
+     * - Server Certificate = self signed certificate
+     * - Server's TLS Server Certificate = self signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection  (direct trust is not allowed with "CA constraint" usage)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_selfsigned_certificate_usage_ca_selfsigned_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(new X509Certificate[] { helper.serverIntX509CertSelfSigned }, + helper.serverIntPrivateKeyFromCert, helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertSelfSigned, CertificateUsage.CA_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = CA constraint
+     * - Server Certificate = intermediate signed certificate/wo chain
+     * - Server's TLS Server Certificate = intermediate signed certificate/wo chain (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection  (direct trust is not allowed with "CA constraint" usage)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_server_certificate_usage_ca_server_cert_wo_chain_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(new X509Certificate[] { helper.serverIntX509CertChain[0] }, + helper.serverIntPrivateKeyFromCert, helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[0], CertificateUsage.CA_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /* ---- SERVICE_CERTIFICATE_CONSTRAINT ---- */ + + /** + *
+     * Test scenario:
+     * - Certificate Usage = service certificate constraint
+     * - Server Certificate = server certificate
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client is able to connect
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_service() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[0], + CertificateUsage.SERVICE_CERTIFICATE_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.waitForRegistrationAtServerSide(1); + + assertNotNull(helper.getCurrentRegistration()); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = service certificate constraint
+     * - Server Certificate = root CA certificate (not end-entity certificate)
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_service_domain_root_ca_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.rootCAX509Cert, CertificateUsage.SERVICE_CERTIFICATE_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = service certificate constraint
+     * - Server Certificate = other end-entity certificate with same dns name signed by same root ca
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_service_other_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverX509Cert, CertificateUsage.SERVICE_CERTIFICATE_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = service certificate constraint
+     * - Server Certificate = self signed certificate given
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_service_selfsigned_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertSelfSigned, + CertificateUsage.SERVICE_CERTIFICATE_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = service certificate constraint
+     * - Server Certificate = self signed certificate
+     * - Server's TLS Server Certificate = self signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection (self-signed is not PKIX chainable)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_selfsigned_certificate_usage_service_selfsigned_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(new X509Certificate[] { helper.serverIntX509CertSelfSigned }, + helper.serverIntPrivateKeyFromCert, helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertSelfSigned, + CertificateUsage.SERVICE_CERTIFICATE_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = service certificate constraint
+     * - Server Certificate = intermediate signed certificate/wo chain
+     * - Server's TLS Server Certificate = intermediate signed certificate/wo chain (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection (missing intermediate CA aka. "server chain configuration problem")
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_server_certificate_usage_service_server_cert_wo_chain_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(new X509Certificate[] { helper.serverIntX509CertChain[0] }, + helper.serverIntPrivateKeyFromCert, helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[0], + CertificateUsage.SERVICE_CERTIFICATE_CONSTRAINT); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /* ---- TRUST_ANCHOR_ASSERTION ---- */ + + /** + *
+     * Test scenario:
+     * - Certificate Usage = trust anchor assertion
+     * - Server Certificate = server certificate
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection  (direct trust is not allowed with "trust constraint" usage)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_taa() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[0], CertificateUsage.TRUST_ANCHOR_ASSERTION); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = trust anchor assertion
+     * - Server Certificate = intermediate CA certificate
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client is able to connect (pkix path terminates in intermediate CA (TA), root CA is not available as client trust store not in use)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_taa_intca_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[1], CertificateUsage.TRUST_ANCHOR_ASSERTION); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.waitForRegistrationAtServerSide(1); + + assertNotNull(helper.getCurrentRegistration()); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = trust anchor assertion
+     * - Server Certificate = root CA certificate
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client is able to connect (root CA cert is part of the chain)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_taa_domain_root_ca_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.rootCAX509Cert, CertificateUsage.TRUST_ANCHOR_ASSERTION); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.waitForRegistrationAtServerSide(1); + + assertNotNull(helper.getCurrentRegistration()); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = trust anchor assertion
+     * - Server Certificate = other end-entity certificate with same dns name signed by same root ca
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_taa_other_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverX509Cert, CertificateUsage.TRUST_ANCHOR_ASSERTION); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = trust anchor assertion
+     * - Server Certificate = self signed certificate given
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_taa_selfsigned_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertSelfSigned, CertificateUsage.TRUST_ANCHOR_ASSERTION); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = trust anchor assertion
+     * - Server Certificate = self signed certificate
+     * - Server's TLS Server Certificate = self signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection  (direct trust is not allowed with "trust anchor" usage)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_selfsigned_certificate_usage_taa_selfsigned_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(new X509Certificate[] { helper.serverIntX509CertSelfSigned }, + helper.serverIntPrivateKeyFromCert, helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertSelfSigned, CertificateUsage.TRUST_ANCHOR_ASSERTION); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = trust anchor assertion
+     * - Server Certificate = intermediate signed certificate/wo chain
+     * - Server's TLS Server Certificate = intermediate signed certificate/wo chain (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection  (direct trust is not allowed with "trust anchor" usage)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_server_certificate_usage_taa_server_cert_wo_chain_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(new X509Certificate[] { helper.serverIntX509CertChain[0] }, + helper.serverIntPrivateKeyFromCert, helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[0], CertificateUsage.TRUST_ANCHOR_ASSERTION); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /* ---- DOMAIN_ISSUER_CERTIFICATE ---- */ + + /** + *
+     * Test scenario:
+     * - Certificate Usage = domain issuer certificate
+     * - Server Certificate = server certificate
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client is able to connect
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_domain() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[0], CertificateUsage.DOMAIN_ISSUER_CERTIFICATE); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.waitForRegistrationAtServerSide(1); + + assertNotNull(helper.getCurrentRegistration()); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = domain issuer certificate
+     * - Server Certificate = root CA certificate (not end-entity certificate)
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection (no end-entity certificate given)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_domain_root_ca_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.rootCAX509Cert, CertificateUsage.DOMAIN_ISSUER_CERTIFICATE); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = domain issuer certificate
+     * - Server Certificate = other end-entity certificate with same dns name signed by same root ca
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection (different server cert given even thou hostname matches)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_domain_other_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverX509Cert, CertificateUsage.DOMAIN_ISSUER_CERTIFICATE); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = domain issuer certificate
+     * - Server Certificate = self signed certificate given
+     * - Server's TLS Server Certificate = intermediate signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client denied the connection (different certificate self-signed vs. signed -- even thou the public key is same)
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_rootca_certificate_usage_domain_selfsigned_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(helper.serverIntX509CertChain, helper.serverIntPrivateKeyFromCert, + helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertSelfSigned, + CertificateUsage.DOMAIN_ISSUER_CERTIFICATE); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.ensureNoRegistration(1); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = domain issuer certificate
+     * - Server Certificate = self signed certificate
+     * - Server's TLS Server Certificate = self signed certificate (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client is able to connect
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_selfsigned_certificate_usage_domain_selfsigned_server_cert_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(new X509Certificate[] { helper.serverIntX509CertSelfSigned }, + helper.serverIntPrivateKeyFromCert, helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertSelfSigned, + CertificateUsage.DOMAIN_ISSUER_CERTIFICATE); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.waitForRegistrationAtServerSide(1); + + assertNotNull(helper.getCurrentRegistration()); + } + + /** + *
+     * Test scenario:
+     * - Certificate Usage = service certificate constraint
+     * - Server Certificate = intermediate signed certificate/wo chain
+     * - Server's TLS Server Certificate = intermediate signed certificate/wo chain (with SAN DNS entry)
+     * - Server accepts client
+     * - Client Trust Store = root CA
+     *
+     * Expected outcome:
+     * - Client is able to connect
+     * 
+ */ + @Test + public void registered_device_with_x509cert_to_server_with_x509cert_server_certificate_usage_domain_server_cert_wo_chain_given() + throws NonUniqueSecurityInfoException, CertificateEncodingException { + helper.createServerWithX509Cert(new X509Certificate[] { helper.serverIntX509CertChain[0] }, + helper.serverIntPrivateKeyFromCert, helper.trustedCertificates, true); + + helper.server.start(); + + helper.setEndpointNameFromX509(helper.clientX509Cert); + + helper.createX509CertClient(new X509Certificate[] { helper.clientX509Cert }, helper.clientPrivateKeyFromCert, + helper.clientTrustStore, helper.serverIntX509CertChain[0], CertificateUsage.DOMAIN_ISSUER_CERTIFICATE); + + helper.getSecurityStore().add(SecurityInfo.newX509CertInfo(helper.getCurrentEndpoint())); + + helper.assertClientNotRegisterered(); + helper.client.start(); + helper.waitForRegistrationAtServerSide(1); + + assertNotNull(helper.getCurrentRegistration()); + } + + /* ---- */ + @Test public void registered_device_with_x509cert_to_server_with_rpk() throws NonUniqueSecurityInfoException, CertificateEncodingException {