Fix for ONOS-6766: "NETCONF: Exception when using SSH keys and Apache Mina SSHD"
    Modified SSH key handling. Now using BouncyCastle. (Update #2)

Change-Id: I27d8aefba6ed5548b9caa592fb5787cf98dfb5b6
diff --git a/features/BUCK b/features/BUCK
index 8094ff9..bb87afc 100644
--- a/features/BUCK
+++ b/features/BUCK
@@ -36,6 +36,8 @@
     '//lib:commons-io',
     '//lib:jersey-client',
     '//lib:mapdb',
+    '//lib:bcpkix-jdk15on',
+    '//lib:bcprov-jdk15on',
   ]
 )
 
diff --git a/lib/BUCK b/lib/BUCK
index 87add7d..1ca9fbb 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -1,4 +1,4 @@
-# ***** This file was auto-generated at Thu, 31 Aug 2017 21:26:06 GMT. Do not edit this file manually. *****
+# ***** This file was auto-generated at Sun, 3 Sep 2017 12:12:12 GMT. Do not edit this file manually. *****
 # ***** Use onos-lib-gen *****
 
 pass_thru_pom(
@@ -1491,3 +1491,21 @@
   visibility = [ 'PUBLIC' ],
 )
 
+remote_jar (
+  name = 'bcpkix-jdk15on',
+  out = 'bcpkix-jdk15on-1.58.jar',
+  url = 'mvn:org.bouncycastle:bcpkix-jdk15on:jar:1.58',
+  sha1 = '15a760a039b040e767a75c77ffcc4ff62558f903',
+  maven_coords = 'org.bouncycastle:bcpkix-jdk15on:1.58',
+  visibility = [ 'PUBLIC' ],
+)
+
+remote_jar (
+  name = 'bcprov-jdk15on',
+  out = 'bcprov-jdk15on-1.58.jar',
+  url = 'mvn:org.bouncycastle:bcprov-jdk15on:jar:1.58',
+  sha1 = '2c9aa1c4e3372b447ba5daabade4adf2a2264b12',
+  maven_coords = 'org.bouncycastle:bcprov-jdk15on:1.58',
+  visibility = [ 'PUBLIC' ],
+)
+
diff --git a/lib/deps.json b/lib/deps.json
index 35282c4..7ed72bc 100644
--- a/lib/deps.json
+++ b/lib/deps.json
@@ -266,6 +266,8 @@
     "google-truth-0.28": "mvn:com.google.truth:truth:0.28",
     "google-code-findbugs-3.0.0": "mvn:com.google.code.findbugs:jsr305:3.0.0",
     "google-errorprone-2.0.19": "mvn:com.google.errorprone:error_prone_annotations:2.0.19",
-    "google-instrumentation-0.3.0": "mvn:com.google.instrumentation:instrumentation-api:0.3.0"
+    "google-instrumentation-0.3.0": "mvn:com.google.instrumentation:instrumentation-api:0.3.0",
+    "bcpkix-jdk15on": "mvn:org.bouncycastle:bcpkix-jdk15on:1.58",
+    "bcprov-jdk15on": "mvn:org.bouncycastle:bcprov-jdk15on:1.58"
   }
 }
diff --git a/protocols/netconf/ctl/BUCK b/protocols/netconf/ctl/BUCK
index 2d79045..8abf233 100644
--- a/protocols/netconf/ctl/BUCK
+++ b/protocols/netconf/ctl/BUCK
@@ -6,6 +6,8 @@
     '//cli:onos-cli',
     '//lib:org.apache.karaf.shell.console',
     '//lib:sshd-core',
+    '//lib:bcpkix-jdk15on',
+    '//lib:bcprov-jdk15on',
 ]
 
 TEST_DEPS = [
diff --git a/protocols/netconf/ctl/pom.xml b/protocols/netconf/ctl/pom.xml
index c4108ae..0306e181 100644
--- a/protocols/netconf/ctl/pom.xml
+++ b/protocols/netconf/ctl/pom.xml
@@ -78,6 +78,18 @@
             <artifactId>org.apache.karaf.shell.console</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+            <version>1.58</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <version>1.58</version>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfControllerImpl.java b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfControllerImpl.java
index daba5be..a1797d7 100644
--- a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfControllerImpl.java
+++ b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfControllerImpl.java
@@ -24,6 +24,7 @@
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.onlab.packet.IpAddress;
 import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.net.AnnotationKeys;
@@ -49,6 +50,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.security.Security;
 import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.Map;
@@ -128,6 +130,7 @@
     public void activate(ComponentContext context) {
         cfgService.registerProperties(getClass());
         modified(context);
+        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
         log.info("Started");
     }
 
@@ -140,6 +143,7 @@
         cfgService.unregisterProperties(getClass(), false);
         netconfDeviceListeners.clear();
         netconfDeviceMap.clear();
+        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
         log.info("Stopped");
     }
 
diff --git a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfSessionMinaImpl.java b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfSessionMinaImpl.java
index 357ae16..241ea23 100644
--- a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfSessionMinaImpl.java
+++ b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfSessionMinaImpl.java
@@ -28,6 +28,10 @@
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.PEMKeyPair;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
 import org.onosproject.netconf.DatastoreId;
 import org.onosproject.netconf.NetconfDeviceInfo;
 import org.onosproject.netconf.NetconfDeviceOutputEvent;
@@ -39,12 +43,11 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import java.io.CharArrayReader;
 import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.StandardCharsets;
 import java.security.KeyFactory;
 import java.security.KeyPair;
 import java.security.NoSuchAlgorithmException;
@@ -208,23 +211,15 @@
         session = connectFuture.getSession();
         //Using the device ssh key if possible
         if (deviceInfo.getKey() != null) {
-            ByteBuffer buf = StandardCharsets.UTF_8.encode(CharBuffer.wrap(deviceInfo.getKey()));
-            byte[] byteKey = new byte[buf.limit()];
-            buf.get(byteKey);
-            PublicKey key;
+            PEMParser pemParser = new PEMParser(new CharArrayReader(deviceInfo.getKey()));
+            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
             try {
-                key = getPublicKey(byteKey, RSA);
-            } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
-                try {
-                    key = getPublicKey(byteKey, DSA);
-                } catch (NoSuchAlgorithmException | InvalidKeySpecException e1) {
-                    throw new NetconfException("Failed to authenticate session with device " +
-                            deviceInfo + "check key to be the " +
-                            "proper DSA or RSA key", e1);
-                }
+                KeyPair kp = converter.getKeyPair((PEMKeyPair) pemParser.readObject());
+                session.addPublicKeyIdentity(kp);
+            } catch (java.io.IOException e) {
+                throw new NetconfException("Failed to authenticate session with device " +
+                                           deviceInfo + "check key to be a valid key", e);
             }
-            //privateKye can set tu null because is not used by the method.
-            session.addPublicKeyIdentity(new KeyPair(key, null));
         } else {
             session.addPasswordIdentity(deviceInfo.password());
         }