fed2e6d83803e5a5924c0d019ee93f76e39aa33f
[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.buildInlineOrTruststore;
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.rev231228.EcPrivateKeyFormat;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev231228.PrivateKeyFormat;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev231228.PublicKeyFormat;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev231228.RsaPrivateKeyFormat;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev231228.SshPublicKeyFormat;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev231228.SubjectPublicKeyInfoFormat;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tls.client.rev231228.tls.client.grouping.server.authentication.CaCertsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tls.client.rev231228.tls.client.grouping.server.authentication.EeCertsBuilder;
42
43 class ConfigUtilsTest {
44
45     private KeyStore keyStore;
46
47     @BeforeEach
48     void setup() throws Exception {
49         keyStore = KeyStoreUtils.newKeyStore();
50     }
51
52     @Test
53     void setX509Certificates() throws Exception {
54         final var rsaCertData = generateX509CertData("RSA");
55         final var ecCertData = generateX509CertData("EC");
56
57         // not defined -- ignore
58         ConfigUtils.setX509Certificates(keyStore, null, null);
59         assertFalse(keyStore.aliases().hasMoreElements());
60
61         // defined
62         final var inlineOrTruststore = buildInlineOrTruststore(
63                 Map.of("cert-rsa", rsaCertData.certBytes(), "cert-ec", ecCertData.certBytes()));
64         final var caCerts = new CaCertsBuilder().setInlineOrTruststore(inlineOrTruststore).build();
65         final var eeCerts = new EeCertsBuilder().setInlineOrTruststore(inlineOrTruststore).build();
66         ConfigUtils.setX509Certificates(keyStore, caCerts, eeCerts);
67
68         final List<String> aliases = Collections.list(keyStore.aliases());
69         final Set<String> expectedAliases = Set.of("ca-cert-rsa", "ca-cert-ec", "ee-cert-rsa", "ee-cert-ec");
70         assertNotNull(aliases);
71         assertEquals(4, aliases.size());
72         assertEquals(expectedAliases, Set.copyOf(aliases));
73         for (String alias : aliases) {
74             assertTrue(keyStore.isCertificateEntry(alias));
75             assertNotNull(keyStore.getCertificate(alias));
76         }
77     }
78
79     @ParameterizedTest(name = "Set private key from pair: {0}")
80     @MethodSource("asymmetricKeyArgs")
81     @Disabled
82         // raw public key is not implemented yet
83     void setPrivateKeyFromKeyPair(final String testDesc,
84             final PublicKeyFormat publicKeyFormat, final byte[] publicKeyBytes,
85             final PrivateKeyFormat privateKeyFormat, final byte[] privateKeyBytes,
86             final byte[] certificateBytes) throws Exception {
87         final var rawPrivateKey = buildAsymmetricKeyGrouping(publicKeyFormat, publicKeyBytes,
88                 privateKeyFormat, privateKeyBytes);
89         ConfigUtils.setAsymmetricKey(keyStore, rawPrivateKey);
90         assertTrue(keyStore.containsAlias(DEFAULT_PRIVATE_KEY_ALIAS));
91         assertTrue(keyStore.isKeyEntry(DEFAULT_PRIVATE_KEY_ALIAS));
92         assertNotNull(keyStore.getKey(DEFAULT_PRIVATE_KEY_ALIAS, EMPTY_SECRET));
93     }
94
95     @ParameterizedTest(name = "End entity certificate: {0}")
96     @MethodSource("asymmetricKeyArgs")
97     void setEndEntityCertificateWithKey(final String testDesc,
98             final PublicKeyFormat publicKeyFormat, final byte[] publicKeyBytes,
99             final PrivateKeyFormat privateKeyFormat, final byte[] privateKeyBytes,
100             final byte[] certificateBytes) throws Exception {
101         final var endEntityCert = buildEndEntityCertWithKeyGrouping(publicKeyFormat, publicKeyBytes,
102                 privateKeyFormat, privateKeyBytes, certificateBytes);
103         ConfigUtils.setEndEntityCertificateWithKey(keyStore, endEntityCert);
104
105         assertTrue(keyStore.containsAlias(DEFAULT_PRIVATE_KEY_ALIAS));
106         assertTrue(keyStore.isKeyEntry(DEFAULT_PRIVATE_KEY_ALIAS));
107         assertNotNull(keyStore.getKey(DEFAULT_PRIVATE_KEY_ALIAS, EMPTY_SECRET));
108
109         assertTrue(keyStore.containsAlias(DEFAULT_CERTIFICATE_ALIAS));
110         assertTrue(keyStore.isCertificateEntry(DEFAULT_CERTIFICATE_ALIAS));
111         assertNotNull(keyStore.getCertificate(DEFAULT_CERTIFICATE_ALIAS));
112     }
113
114     private static Stream<Arguments> asymmetricKeyArgs() throws Exception {
115         // (test case descriptor, public key format, public key bytes, private key format, private key bytes,
116         // certificate bytes)
117         final var rsaCertData = generateX509CertData("RSA");
118         final var ecCertData = generateX509CertData("EC");
119         return Stream.of(
120                 Arguments.of("RSA / subject-public-key-info",
121                         SubjectPublicKeyInfoFormat.VALUE, rsaCertData.publicKey(),
122                         RsaPrivateKeyFormat.VALUE, rsaCertData.privateKey(),
123                         rsaCertData.certBytes()),
124                 Arguments.of("RSA / ssh-public-key",
125                         SshPublicKeyFormat.VALUE, rsaCertData.sshPublicKey(),
126                         RsaPrivateKeyFormat.VALUE, rsaCertData.privateKey(),
127                         rsaCertData.certBytes()),
128                 Arguments.of("EC / subject-public-key-info",
129                         SubjectPublicKeyInfoFormat.VALUE, ecCertData.publicKey(),
130                         EcPrivateKeyFormat.VALUE, ecCertData.privateKey(),
131                         ecCertData.certBytes()),
132                 Arguments.of("EC / ssh-public-key",
133                         SshPublicKeyFormat.VALUE, ecCertData.sshPublicKey(),
134                         EcPrivateKeyFormat.VALUE, ecCertData.privateKey(),
135                         ecCertData.certBytes())
136         );
137     }
138 }