acd9df1f9171424536a1d94b519ac13556a1e46e
[netconf.git] / transport / transport-tls / src / test / java / org / opendaylight / netconf / transport / tls / ConfigUtilsTest.java
1 /*
2  * Copyright (c) 2023 PANTHEON.tech s.r.o. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netconf.transport.tls;
9
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertFalse;
12 import static org.junit.jupiter.api.Assertions.assertNotNull;
13 import static org.junit.jupiter.api.Assertions.assertTrue;
14 import static org.opendaylight.netconf.transport.tls.ConfigUtils.DEFAULT_CERTIFICATE_ALIAS;
15 import static org.opendaylight.netconf.transport.tls.ConfigUtils.DEFAULT_PRIVATE_KEY_ALIAS;
16 import static org.opendaylight.netconf.transport.tls.ConfigUtils.EMPTY_SECRET;
17 import static org.opendaylight.netconf.transport.tls.TestUtils.buildAsymmetricKeyGrouping;
18 import static org.opendaylight.netconf.transport.tls.TestUtils.buildEndEntityCertWithKeyGrouping;
19 import static org.opendaylight.netconf.transport.tls.TestUtils.buildLocalOrTruststore;
20 import static org.opendaylight.netconf.transport.tls.TestUtils.generateX509CertData;
21
22 import java.security.KeyStore;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.stream.Stream;
28 import org.junit.jupiter.api.BeforeEach;
29 import org.junit.jupiter.api.Disabled;
30 import org.junit.jupiter.api.Test;
31 import org.junit.jupiter.params.ParameterizedTest;
32 import org.junit.jupiter.params.provider.Arguments;
33 import org.junit.jupiter.params.provider.MethodSource;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev221212.EcPrivateKeyFormat;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev221212.PrivateKeyFormat;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev221212.PublicKeyFormat;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev221212.RsaPrivateKeyFormat;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev221212.SshPublicKeyFormat;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev221212.SubjectPublicKeyInfoFormat;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tls.client.rev221212.tls.client.grouping.server.authentication.CaCerts;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tls.client.rev221212.tls.client.grouping.server.authentication.CaCertsBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tls.client.rev221212.tls.client.grouping.server.authentication.EeCerts;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tls.client.rev221212.tls.client.grouping.server.authentication.EeCertsBuilder;
44
45 class ConfigUtilsTest {
46
47     private KeyStore keyStore;
48
49     @BeforeEach
50     void setup() throws Exception {
51         keyStore = KeyStoreUtils.newKeyStore();
52     }
53
54     @Test
55     void setX509Certificates() throws Exception {
56         final var rsaCertData = generateX509CertData("RSA");
57         final var ecCertData = generateX509CertData("EC");
58
59         // not defined -- ignore
60         ConfigUtils.setX509Certificates(keyStore, null, null);
61         assertFalse(keyStore.aliases().hasMoreElements());
62
63         // defined
64         final var localOrTruststore = buildLocalOrTruststore(
65                 Map.of("cert-rsa", rsaCertData.certBytes(), "cert-ec", ecCertData.certBytes()));
66         final CaCerts caCerts = new CaCertsBuilder().setLocalOrTruststore(localOrTruststore).build();
67         final EeCerts eeCerts = new EeCertsBuilder().setLocalOrTruststore(localOrTruststore).build();
68         ConfigUtils.setX509Certificates(keyStore, caCerts, eeCerts);
69
70         final List<String> aliases = Collections.list(keyStore.aliases());
71         final Set<String> expectedAliases = Set.of("ca-cert-rsa", "ca-cert-ec", "ee-cert-rsa", "ee-cert-ec");
72         assertNotNull(aliases);
73         assertEquals(4, aliases.size());
74         assertEquals(expectedAliases, Set.copyOf(aliases));
75         for (String alias : aliases) {
76             assertTrue(keyStore.isCertificateEntry(alias));
77             assertNotNull(keyStore.getCertificate(alias));
78         }
79     }
80
81     @ParameterizedTest(name = "Set private key from pair: {0}")
82     @MethodSource("asymmetricKeyArgs")
83     @Disabled
84         // raw public key is not implemented yet
85     void setPrivateKeyFromKeyPair(final String testDesc,
86             final PublicKeyFormat publicKeyFormat, final byte[] publicKeyBytes,
87             final PrivateKeyFormat privateKeyFormat, final byte[] privateKeyBytes,
88             final byte[] certificateBytes) throws Exception {
89         final var rawPrivateKey = buildAsymmetricKeyGrouping(publicKeyFormat, publicKeyBytes,
90                 privateKeyFormat, privateKeyBytes);
91         ConfigUtils.setAsymmetricKey(keyStore, rawPrivateKey);
92         assertTrue(keyStore.containsAlias(DEFAULT_PRIVATE_KEY_ALIAS));
93         assertTrue(keyStore.isKeyEntry(DEFAULT_PRIVATE_KEY_ALIAS));
94         assertNotNull(keyStore.getKey(DEFAULT_PRIVATE_KEY_ALIAS, EMPTY_SECRET));
95     }
96
97     @ParameterizedTest(name = "End entity certificate: {0}")
98     @MethodSource("asymmetricKeyArgs")
99     void setEndEntityCertificateWithKey(final String testDesc,
100             final PublicKeyFormat publicKeyFormat, final byte[] publicKeyBytes,
101             final PrivateKeyFormat privateKeyFormat, final byte[] privateKeyBytes,
102             final byte[] certificateBytes) throws Exception {
103         final var endEntityCert = buildEndEntityCertWithKeyGrouping(publicKeyFormat, publicKeyBytes,
104                 privateKeyFormat, privateKeyBytes, certificateBytes);
105         ConfigUtils.setEndEntityCertificateWithKey(keyStore, endEntityCert);
106
107         assertTrue(keyStore.containsAlias(DEFAULT_PRIVATE_KEY_ALIAS));
108         assertTrue(keyStore.isKeyEntry(DEFAULT_PRIVATE_KEY_ALIAS));
109         assertNotNull(keyStore.getKey(DEFAULT_PRIVATE_KEY_ALIAS, EMPTY_SECRET));
110
111         assertTrue(keyStore.containsAlias(DEFAULT_CERTIFICATE_ALIAS));
112         assertTrue(keyStore.isCertificateEntry(DEFAULT_CERTIFICATE_ALIAS));
113         assertNotNull(keyStore.getCertificate(DEFAULT_CERTIFICATE_ALIAS));
114     }
115
116     private static Stream<Arguments> asymmetricKeyArgs() throws Exception {
117         // (test case descriptor, public key format, public key bytes, private key format, private key bytes,
118         // certificate bytes)
119         final var rsaCertData = generateX509CertData("RSA");
120         final var ecCertData = generateX509CertData("EC");
121         return Stream.of(
122                 Arguments.of("RSA / subject-public-key-info",
123                         SubjectPublicKeyInfoFormat.VALUE, rsaCertData.publicKey(),
124                         RsaPrivateKeyFormat.VALUE, rsaCertData.privateKey(),
125                         rsaCertData.certBytes()),
126                 Arguments.of("RSA / ssh-public-key",
127                         SshPublicKeyFormat.VALUE, rsaCertData.sshPublicKey(),
128                         RsaPrivateKeyFormat.VALUE, rsaCertData.privateKey(),
129                         rsaCertData.certBytes()),
130                 Arguments.of("EC / subject-public-key-info",
131                         SubjectPublicKeyInfoFormat.VALUE, ecCertData.publicKey(),
132                         EcPrivateKeyFormat.VALUE, ecCertData.privateKey(),
133                         ecCertData.certBytes()),
134                 Arguments.of("EC / ssh-public-key",
135                         SshPublicKeyFormat.VALUE, ecCertData.sshPublicKey(),
136                         EcPrivateKeyFormat.VALUE, ecCertData.privateKey(),
137                         ecCertData.certBytes())
138         );
139     }
140 }