From 83a4f5f2f0013b7d32cd8d1f2ff849b4c9090766 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Tue, 7 Apr 2020 13:23:36 +0000
Subject: [PATCH] Transport: Hang the X25519 keygen thread off CommSystem so
 Ratchet can use it Don't start NTCP if neither 1 nor 2 is enabled

---
 .../src/net/i2p/router/CommSystemFacade.java  |  7 +++++++
 .../i2p/router/crypto/ratchet/Elligator2.java |  2 +-
 .../i2p/router/crypto/ratchet/RatchetSKM.java |  5 ++---
 .../router/crypto/ratchet/RatchetTagSet.java  |  3 ++-
 .../transport/CommSystemFacadeImpl.java       | 10 ++++++++++
 .../router/transport/TransportManager.java    | 19 ++++++++++++++++---
 6 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/router/java/src/net/i2p/router/CommSystemFacade.java b/router/java/src/net/i2p/router/CommSystemFacade.java
index 78b71a7eec..e5e77f9825 100644
--- a/router/java/src/net/i2p/router/CommSystemFacade.java
+++ b/router/java/src/net/i2p/router/CommSystemFacade.java
@@ -22,6 +22,7 @@ import net.i2p.data.router.RouterAddress;
 import net.i2p.data.router.RouterInfo;
 import net.i2p.router.transport.Transport;
 import net.i2p.router.transport.crypto.DHSessionKeyBuilder;
+import net.i2p.router.transport.crypto.X25519KeyFactory;
 import net.i2p.util.Translate;
 
 /**
@@ -198,6 +199,12 @@ public abstract class CommSystemFacade implements Service {
      */
     public DHSessionKeyBuilder.Factory getDHFactory() { return null; }
 
+    /**
+     *  Factory for making X25519 key pairs.
+     *  @since 0.9.46
+     */
+    public X25519KeyFactory getXDHFactory() { return null; }
+
     /**
      *  Router must call after netdb is initialized
      *  @since 0.9.41
diff --git a/router/java/src/net/i2p/router/crypto/ratchet/Elligator2.java b/router/java/src/net/i2p/router/crypto/ratchet/Elligator2.java
index 08f4dbf363..65f9cc0730 100644
--- a/router/java/src/net/i2p/router/crypto/ratchet/Elligator2.java
+++ b/router/java/src/net/i2p/router/crypto/ratchet/Elligator2.java
@@ -15,7 +15,7 @@ import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
 import net.i2p.data.DataHelper;
 import net.i2p.data.PrivateKey;
 import net.i2p.data.PublicKey;
-import net.i2p.router.transport.crypto.X25519KeyFactory;
+//import net.i2p.router.transport.crypto.X25519KeyFactory;
 import net.i2p.util.HexDump;
 import net.i2p.util.NativeBigInteger;
 
diff --git a/router/java/src/net/i2p/router/crypto/ratchet/RatchetSKM.java b/router/java/src/net/i2p/router/crypto/ratchet/RatchetSKM.java
index fb9af25bf3..bc54427e78 100644
--- a/router/java/src/net/i2p/router/crypto/ratchet/RatchetSKM.java
+++ b/router/java/src/net/i2p/router/crypto/ratchet/RatchetSKM.java
@@ -19,7 +19,6 @@ import java.util.concurrent.LinkedBlockingQueue;
 
 import com.southernstorm.noise.protocol.HandshakeState;
 
-import net.i2p.I2PAppContext;
 import net.i2p.crypto.EncType;
 import net.i2p.crypto.HKDF;
 import net.i2p.crypto.KeyPair;
@@ -49,7 +48,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
     private final HashMap<PublicKey, List<OutboundSession>> _pendingOutboundSessions;
     /** Map allowing us to go from a SessionTag to the containing RatchetTagSet */
     private final ConcurrentHashMap<RatchetSessionTag, RatchetTagSet> _inboundTagSets;
-    protected final I2PAppContext _context;
+    protected final RouterContext _context;
     private volatile boolean _alive;
     private final HKDF _hkdf;
     private final DecayingHashSet _replayFilter;
@@ -1165,7 +1164,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
                         // new keys for 0,2,4,...
                         if (!isRequest && _log.shouldWarn())
                             _log.warn("Got reverse w/o request, generating new key anyway " + key);
-                        _myIBKeys = _context.keyGenerator().generatePKIKeys(EncType.ECIES_X25519);
+                        _myIBKeys = _context.commSystem().getXDHFactory().getKeys();
                         _myIBKeyID++;
                         _myIBKey = new NextSessionKey(_myIBKeys.getPublic().getData(), _myIBKeyID, true, false);
                     } else {
diff --git a/router/java/src/net/i2p/router/crypto/ratchet/RatchetTagSet.java b/router/java/src/net/i2p/router/crypto/ratchet/RatchetTagSet.java
index 1c7049e345..2e1475daf3 100644
--- a/router/java/src/net/i2p/router/crypto/ratchet/RatchetTagSet.java
+++ b/router/java/src/net/i2p/router/crypto/ratchet/RatchetTagSet.java
@@ -20,6 +20,7 @@ import net.i2p.data.Base64;
 import net.i2p.data.DataHelper;
 import net.i2p.data.PublicKey;
 import net.i2p.data.SessionKey;
+import net.i2p.router.RouterContext;
 import net.i2p.util.Log;
 
 /**
@@ -331,7 +332,7 @@ class RatchetTagSet implements TagSetHandle {
             boolean isFirst = _id == 0;
             if (isFirst || (_id & 0x01) != 0) {
                 // new keys only needed first time and odd times
-                _nextKeys = I2PAppContext.getGlobalContext().keyGenerator().generatePKIKeys(EncType.ECIES_X25519);
+                _nextKeys = ((RouterContext) I2PAppContext.getGlobalContext()).commSystem().getXDHFactory().getKeys();
                 _nextKey = new NextSessionKey(_nextKeys.getPublic().getData(), _keyid + 1, false, isFirst);
             } else {
                 // even times, just send old ID
diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
index 659e553ee7..86f9651db8 100644
--- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
+++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
@@ -25,6 +25,7 @@ import net.i2p.router.CommSystemFacade;
 import net.i2p.router.OutNetMessage;
 import net.i2p.router.RouterContext;
 import net.i2p.router.transport.crypto.DHSessionKeyBuilder;
+import net.i2p.router.transport.crypto.X25519KeyFactory;
 import net.i2p.router.transport.udp.UDPTransport;
 import net.i2p.router.util.EventLog;
 import net.i2p.util.Addresses;
@@ -366,6 +367,15 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
     public DHSessionKeyBuilder.Factory getDHFactory() {
         return _manager.getDHFactory();
     }
+
+    /**
+     *  Factory for making X25519 key pairs.
+     *  @since 0.9.46
+     */
+    @Override
+    public X25519KeyFactory getXDHFactory() {
+        return _manager.getXDHFactory();
+    }
     
     /*
      * GeoIP stuff
diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java
index abcf95faf4..c9627ac5bd 100644
--- a/router/java/src/net/i2p/router/transport/TransportManager.java
+++ b/router/java/src/net/i2p/router/transport/TransportManager.java
@@ -116,7 +116,8 @@ public class TransportManager implements TransportEventListener {
         boolean enableNTCP2 = isNTCPEnabled(context) &&
                               context.getProperty(PROP_NTCP2_ENABLE, DEFAULT_NTCP2_ENABLE);
         _dhThread = (_enableUDP || enableNTCP2) ? new DHSessionKeyBuilder.PrecalcRunner(context) : null;
-        _xdhThread = enableNTCP2 ? new X25519KeyFactory(context) : null;
+        // always created, even if NTCP2 is not enabled, because ratchet needs it
+        _xdhThread = new X25519KeyFactory(context);
     }
 
     /**
@@ -166,6 +167,14 @@ public class TransportManager implements TransportEventListener {
     DHSessionKeyBuilder.Factory getDHFactory() {
         return _dhThread;
     }
+
+    /**
+     *  Factory for making X25519 key pairs.
+     *  @since 0.9.46
+     */
+    X25519KeyFactory getXDHFactory() {
+        return _xdhThread;
+    }
     
     private void addTransport(Transport transport) {
         if (transport == null) return;
@@ -192,7 +201,9 @@ public class TransportManager implements TransportEventListener {
         }
         if (isNTCPEnabled(_context)) {
             DHSessionKeyBuilder.PrecalcRunner dh = _enableNTCP1 ? _dhThread : null;
-            Transport ntcp = new NTCPTransport(_context, dh, _xdhThread);
+            boolean enableNTCP2 = _context.getProperty(PROP_NTCP2_ENABLE, DEFAULT_NTCP2_ENABLE);
+            X25519KeyFactory xdh = enableNTCP2 ? _xdhThread : null;
+            Transport ntcp = new NTCPTransport(_context, dh, xdh);
             addTransport(ntcp);
             initializeAddress(ntcp);
             if (udp != null) {
@@ -213,7 +224,9 @@ public class TransportManager implements TransportEventListener {
     }
     
     public static boolean isNTCPEnabled(RouterContext ctx) {
-        return ctx.getBooleanPropertyDefaultTrue(PROP_ENABLE_NTCP);
+        return ctx.getBooleanPropertyDefaultTrue(PROP_ENABLE_NTCP) &&
+               (ctx.getProperty(PROP_NTCP1_ENABLE, DEFAULT_NTCP1_ENABLE) ||
+                ctx.getProperty(PROP_NTCP2_ENABLE, DEFAULT_NTCP2_ENABLE));
     }
     
     /**
-- 
GitLab