2 * Copyright (c) 2019 Pantheon Technologies, s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.netconf.sal.connect.util;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.collect.Sets;
13 import io.netty.handler.ssl.SslHandler;
14 import java.io.IOException;
15 import java.security.GeneralSecurityException;
16 import java.security.KeyStore;
18 import javax.net.ssl.KeyManagerFactory;
19 import javax.net.ssl.SSLContext;
20 import javax.net.ssl.SSLEngine;
21 import javax.net.ssl.TrustManagerFactory;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.opendaylight.netconf.client.SslHandlerFactory;
24 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfKeystoreAdapter;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev221225.connection.parameters.protocol.Specification;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev221225.connection.parameters.protocol.specification.TlsCase;
28 public final class SslHandlerFactoryImpl implements SslHandlerFactory {
29 private final NetconfKeystoreAdapter keystoreAdapter;
30 private final @Nullable Specification specification;
32 public SslHandlerFactoryImpl(final NetconfKeystoreAdapter keystoreAdapter) {
33 this(keystoreAdapter, null);
36 public SslHandlerFactoryImpl(final NetconfKeystoreAdapter keystoreAdapter, final Specification specification) {
37 this.keystoreAdapter = requireNonNull(keystoreAdapter);
38 this.specification = specification;
42 public SslHandler createSslHandler() {
43 return createSslHandler(Set.of());
47 public SslHandler createSslHandler(final Set<String> allowedKeys) {
49 final KeyStore keyStore = keystoreAdapter.getJavaKeyStore(allowedKeys);
51 final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
52 kmf.init(keyStore, "".toCharArray());
54 final TrustManagerFactory tmf =
55 TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
58 final SSLContext sslCtx = SSLContext.getInstance("TLS");
59 sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
60 final SSLEngine engine = sslCtx.createSSLEngine();
61 engine.setUseClientMode(true);
63 final String[] engineProtocols = engine.getSupportedProtocols();
64 final String[] enabledProtocols;
65 if (specification instanceof TlsCase tlsSpecification) {
66 final Set<String> protocols = Sets.newHashSet(engineProtocols);
67 protocols.removeAll(tlsSpecification.getTls().getExcludedVersions());
68 enabledProtocols = protocols.toArray(new String[0]);
69 } else if (specification == null) {
70 enabledProtocols = engineProtocols;
72 throw new IllegalArgumentException("Cannot get TLS specification from: " + specification);
75 engine.setEnabledProtocols(enabledProtocols);
76 engine.setEnabledCipherSuites(engine.getSupportedCipherSuites());
77 engine.setEnableSessionCreation(true);
78 return new SslHandler(engine);
79 } catch (GeneralSecurityException | IOException exc) {
80 throw new IllegalStateException(exc);