diff --git a/service/config/sample-secrets-bundle.yml b/service/config/sample-secrets-bundle.yml index 933fa0145..63a0bfdb6 100644 --- a/service/config/sample-secrets-bundle.yml +++ b/service/config/sample-secrets-bundle.yml @@ -98,4 +98,6 @@ linkDevice.secret: AAAAAAAAAAA= tlsKeyStore.password: unset +noiseTunnel.tlsKeyStorePassword: ABCDEFGHIJKLMNOPQRSTUVWXYZ +noiseTunnel.noiseStaticPrivateKey: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= noiseTunnel.recognizedProxySecret: ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789AAAAAAA diff --git a/service/config/sample.yml b/service/config/sample.yml index a6eab4f13..226cc3b55 100644 --- a/service/config/sample.yml +++ b/service/config/sample.yml @@ -464,6 +464,11 @@ callingTurnManualTable: noiseTunnel: port: 8443 + tlsKeyStoreFile: /path/to/file.p12 + tlsKeyStoreEntryAlias: example.com + tlsKeyStorePassword: secret://noiseTunnel.tlsKeyStorePassword + noiseStaticPrivateKey: secret://noiseTunnel.noiseStaticPrivateKey + noiseRootPublicKeySignature: ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz recognizedProxySecret: secret://noiseTunnel.recognizedProxySecret externalRequestFilter: diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index ac82ddbce..3e643eb46 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -28,7 +28,11 @@ import io.micrometer.core.instrument.Metrics; import io.micrometer.core.instrument.binder.grpc.MetricCollectingServerInterceptor; import io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics; import io.netty.channel.local.LocalAddress; +import java.io.FileInputStream; import java.net.http.HttpClient; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; import java.time.Clock; import java.time.Duration; import java.util.ArrayList; @@ -46,6 +50,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.stream.Stream; +import javax.annotation.Nullable; import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.FilterRegistration; @@ -144,6 +149,8 @@ import org.whispersystems.textsecuregcm.grpc.RequestAttributesInterceptor; import org.whispersystems.textsecuregcm.grpc.net.ClientConnectionManager; import org.whispersystems.textsecuregcm.grpc.net.ManagedDefaultEventLoopGroup; import org.whispersystems.textsecuregcm.grpc.net.ManagedLocalGrpcServer; +import org.whispersystems.textsecuregcm.grpc.net.ManagedNioEventLoopGroup; +import org.whispersystems.textsecuregcm.grpc.net.NoiseWebSocketTunnelServer; import org.whispersystems.textsecuregcm.jetty.JettyHttpConfigurationCustomizer; import org.whispersystems.textsecuregcm.limits.CardinalityEstimator; import org.whispersystems.textsecuregcm.limits.PushChallengeManager; @@ -829,9 +836,56 @@ public class WhisperServerService extends Application filters = new ArrayList<>(); filters.add(remoteDeprecationFilter); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/NoiseWebSocketTunnelConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/NoiseWebSocketTunnelConfiguration.java index 45e0832d8..35a370a72 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/NoiseWebSocketTunnelConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/NoiseWebSocketTunnelConfiguration.java @@ -1,8 +1,26 @@ package org.whispersystems.textsecuregcm.configuration; +import javax.annotation.Nullable; import javax.validation.constraints.NotNull; import javax.validation.constraints.Positive; +import org.signal.libsignal.protocol.InvalidKeyException; +import org.signal.libsignal.protocol.ecc.Curve; +import org.signal.libsignal.protocol.ecc.ECKeyPair; +import org.signal.libsignal.protocol.ecc.ECPrivateKey; +import org.whispersystems.textsecuregcm.configuration.secrets.SecretBytes; import org.whispersystems.textsecuregcm.configuration.secrets.SecretString; -public record NoiseWebSocketTunnelConfiguration(@Positive int port, @NotNull SecretString recognizedProxySecret) { +public record NoiseWebSocketTunnelConfiguration(@Positive int port, + @Nullable String tlsKeyStoreFile, + @Nullable String tlsKeyStoreEntryAlias, + @Nullable SecretString tlsKeyStorePassword, + @NotNull SecretBytes noiseStaticPrivateKey, + @NotNull byte[] noiseRootPublicKeySignature, + @NotNull SecretString recognizedProxySecret) { + + public ECKeyPair noiseStaticKeyPair() throws InvalidKeyException { + final ECPrivateKey privateKey = Curve.decodePrivatePoint(noiseStaticPrivateKey().value()); + + return new ECKeyPair(privateKey.publicKey(), privateKey); + } } diff --git a/service/src/test/resources/config/test-secrets-bundle.yml b/service/src/test/resources/config/test-secrets-bundle.yml index d8cfdc935..1dc13ec72 100644 --- a/service/src/test/resources/config/test-secrets-bundle.yml +++ b/service/src/test/resources/config/test-secrets-bundle.yml @@ -131,4 +131,5 @@ linkDevice.secret: AAAAAAAAAAA= tlsKeyStore.password: unset +noiseTunnel.noiseStaticPrivateKey: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= noiseTunnel.recognizedProxySecret: ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789AAAAAAA diff --git a/service/src/test/resources/config/test.yml b/service/src/test/resources/config/test.yml index a390da9b4..21d7ed23c 100644 --- a/service/src/test/resources/config/test.yml +++ b/service/src/test/resources/config/test.yml @@ -443,6 +443,8 @@ callingTurnManualTable: noiseTunnel: port: 8443 + noiseStaticPrivateKey: secret://noiseTunnel.noiseStaticPrivateKey + noiseRootPublicKeySignature: ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyz recognizedProxySecret: secret://noiseTunnel.recognizedProxySecret externalRequestFilter: @@ -452,3 +454,4 @@ externalRequestFilter: - /example permittedInternalRanges: - 127.0.0.0/8 +