aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0777-Use-Velocity-compression-and-cipher-natives.patch
diff options
context:
space:
mode:
authorJake Potrebic <[email protected]>2022-03-04 00:09:43 -0800
committerGitHub <[email protected]>2022-03-04 09:09:43 +0100
commit15b6b3db2cf24c98afbfb0849e694875d18fc021 (patch)
tree03e884d0c7fe2ce292825b5b51ec4c9a6ce2e8cc /patches/server/0777-Use-Velocity-compression-and-cipher-natives.patch
parent753bf2c1034c5f35cc0839001d12363a44f936fc (diff)
downloadPaper-15b6b3db2cf24c98afbfb0849e694875d18fc021.tar.gz
Paper-15b6b3db2cf24c98afbfb0849e694875d18fc021.zip
Add StructuresLocateEvent as replacement for StructureLocateEvent (#7524)
Diffstat (limited to 'patches/server/0777-Use-Velocity-compression-and-cipher-natives.patch')
-rw-r--r--patches/server/0777-Use-Velocity-compression-and-cipher-natives.patch364
1 files changed, 364 insertions, 0 deletions
diff --git a/patches/server/0777-Use-Velocity-compression-and-cipher-natives.patch b/patches/server/0777-Use-Velocity-compression-and-cipher-natives.patch
new file mode 100644
index 0000000000..cb29c8b7b1
--- /dev/null
+++ b/patches/server/0777-Use-Velocity-compression-and-cipher-natives.patch
@@ -0,0 +1,364 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrew Steinborn <[email protected]>
+Date: Mon, 26 Jul 2021 02:15:17 -0400
+Subject: [PATCH] Use Velocity compression and cipher natives
+
+
+diff --git a/build.gradle.kts b/build.gradle.kts
+index f83bed210b97508affd6523065b53f2876f964f0..a205db80a1a8dbe53130c4148b25163741c33406 100644
+--- a/build.gradle.kts
++++ b/build.gradle.kts
+@@ -44,6 +44,11 @@ dependencies {
+ runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.2")
+
+ implementation("net.fabricmc:mapping-io:0.3.0") // Paper - needed to read mappings for stacktrace deobfuscation
++ // Paper start - Use Velocity cipher
++ implementation("com.velocitypowered:velocity-native:1.1.0-SNAPSHOT") {
++ isTransitive = false
++ }
++ // Paper end
+
+ testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test
+ testImplementation("junit:junit:4.13.2")
+diff --git a/src/main/java/net/minecraft/network/CipherDecoder.java b/src/main/java/net/minecraft/network/CipherDecoder.java
+index 778beb445eac5769b9e4e07b4d1294c50ae2602b..c712fb8193115e1ab71b5e40fb0ccb9413062b03 100644
+--- a/src/main/java/net/minecraft/network/CipherDecoder.java
++++ b/src/main/java/net/minecraft/network/CipherDecoder.java
+@@ -7,13 +7,29 @@ import java.util.List;
+ import javax.crypto.Cipher;
+
+ public class CipherDecoder extends MessageToMessageDecoder<ByteBuf> {
+- private final CipherBase cipher;
++ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper
+
+- public CipherDecoder(Cipher cipher) {
+- this.cipher = new CipherBase(cipher);
++ public CipherDecoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper
++ this.cipher = cipher; // Paper
+ }
+
+ protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
+- list.add(this.cipher.decipher(channelHandlerContext, byteBuf));
++ // Paper start
++ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf);
++ try {
++ cipher.process(compatible);
++ list.add(compatible);
++ } catch (Exception e) {
++ compatible.release(); // compatible will never be used if we throw an exception
++ throw e;
++ }
++ // Paper end
+ }
++
++ // Paper start
++ @Override
++ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
++ cipher.close();
++ }
++ // Paper end
+ }
+diff --git a/src/main/java/net/minecraft/network/CipherEncoder.java b/src/main/java/net/minecraft/network/CipherEncoder.java
+index 0f3d502a9680006bcdcd7d272240a2e5c3b46790..5dd7be70603e8754d2625bb9d16900cb01b9c730 100644
+--- a/src/main/java/net/minecraft/network/CipherEncoder.java
++++ b/src/main/java/net/minecraft/network/CipherEncoder.java
+@@ -4,15 +4,32 @@ import io.netty.buffer.ByteBuf;
+ import io.netty.channel.ChannelHandlerContext;
+ import io.netty.handler.codec.MessageToByteEncoder;
+ import javax.crypto.Cipher;
++import java.util.List;
+
+-public class CipherEncoder extends MessageToByteEncoder<ByteBuf> {
+- private final CipherBase cipher;
++public class CipherEncoder extends io.netty.handler.codec.MessageToMessageEncoder<ByteBuf> { // Paper - change superclass
++ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper
+
+- public CipherEncoder(Cipher cipher) {
+- this.cipher = new CipherBase(cipher);
++ public CipherEncoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper
++ this.cipher = cipher; // Paper
+ }
+
+- protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception {
+- this.cipher.encipher(byteBuf, byteBuf2);
++ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
++ // Paper start
++ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf);
++ try {
++ cipher.process(compatible);
++ list.add(compatible);
++ } catch (Exception e) {
++ compatible.release(); // compatible will never be used if we throw an exception
++ throw e;
++ }
++ // Paper end
+ }
++
++ // Paper start
++ @Override
++ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
++ cipher.close();
++ }
++ // Paper end
+ }
+diff --git a/src/main/java/net/minecraft/network/CompressionDecoder.java b/src/main/java/net/minecraft/network/CompressionDecoder.java
+index b62be99c57b0a5bba0dc29809557d4d247698b13..f4d4ad983baf24d889441541d5a84dc1f49ea4d4 100644
+--- a/src/main/java/net/minecraft/network/CompressionDecoder.java
++++ b/src/main/java/net/minecraft/network/CompressionDecoder.java
+@@ -12,13 +12,20 @@ public class CompressionDecoder extends ByteToMessageDecoder {
+ public static final int MAXIMUM_COMPRESSED_LENGTH = 2097152;
+ public static final int MAXIMUM_UNCOMPRESSED_LENGTH = 8388608;
+ private final Inflater inflater;
++ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper
+ private int threshold;
+ private boolean validateDecompressed;
+
++ // Paper start
+ public CompressionDecoder(int compressionThreshold, boolean rejectsBadPackets) {
++ this(null, compressionThreshold, rejectsBadPackets);
++ }
++ public CompressionDecoder(com.velocitypowered.natives.compression.VelocityCompressor compressor, int compressionThreshold, boolean rejectsBadPackets) {
+ this.threshold = compressionThreshold;
+ this.validateDecompressed = rejectsBadPackets;
+- this.inflater = new Inflater();
++ this.inflater = compressor == null ? new Inflater() : null;
++ this.compressor = compressor;
++ // Paper end
+ }
+
+ protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
+@@ -38,6 +45,8 @@ public class CompressionDecoder extends ByteToMessageDecoder {
+ }
+ }
+
++ // Paper start
++ if (this.inflater != null) {
+ byte[] bs = new byte[friendlyByteBuf.readableBytes()];
+ friendlyByteBuf.readBytes(bs);
+ this.inflater.setInput(bs);
+@@ -45,10 +54,36 @@ public class CompressionDecoder extends ByteToMessageDecoder {
+ this.inflater.inflate(cs);
+ list.add(Unpooled.wrappedBuffer(cs));
+ this.inflater.reset();
++ return;
++ }
++
++ int claimedUncompressedSize = i; // OBFHELPER
++ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf);
++ ByteBuf uncompressed = com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(channelHandlerContext.alloc(), this.compressor, claimedUncompressedSize);
++ try {
++ this.compressor.inflate(compatibleIn, uncompressed, claimedUncompressedSize);
++ list.add(uncompressed);
++ byteBuf.clear();
++ } catch (Exception e) {
++ uncompressed.release();
++ throw e;
++ } finally {
++ compatibleIn.release();
++ }
++ // Paper end
+ }
+ }
+ }
+
++ // Paper start
++ @Override
++ public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception {
++ if (this.compressor != null) {
++ this.compressor.close();
++ }
++ }
++ // Paper end
++
+ public void setThreshold(int compressionThreshold, boolean rejectsBadPackets) {
+ this.threshold = compressionThreshold;
+ this.validateDecompressed = rejectsBadPackets;
+diff --git a/src/main/java/net/minecraft/network/CompressionEncoder.java b/src/main/java/net/minecraft/network/CompressionEncoder.java
+index 792883afe53d2b7989c25a81c2f9a639d5e21d20..c04379ca8a4db0f4de46ad2b3b3384310eebddf3 100644
+--- a/src/main/java/net/minecraft/network/CompressionEncoder.java
++++ b/src/main/java/net/minecraft/network/CompressionEncoder.java
+@@ -6,22 +6,37 @@ import io.netty.handler.codec.MessageToByteEncoder;
+ import java.util.zip.Deflater;
+
+ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
+- private final byte[] encodeBuf = new byte[8192];
++ private final byte[] encodeBuf; // Paper
+ private final Deflater deflater;
++ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper
+ private int threshold;
+
++ // Paper start
+ public CompressionEncoder(int compressionThreshold) {
++ this(null, compressionThreshold);
++ }
++ public CompressionEncoder(com.velocitypowered.natives.compression.VelocityCompressor compressor, int compressionThreshold) {
+ this.threshold = compressionThreshold;
+- this.deflater = new Deflater();
++ if (compressor == null) {
++ this.encodeBuf = new byte[8192];
++ this.deflater = new Deflater();
++ } else {
++ this.encodeBuf = null;
++ this.deflater = null;
++ }
++ this.compressor = compressor;
++ // Paper end
+ }
+
+- protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) {
++ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { // Paper
+ int i = byteBuf.readableBytes();
+ FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf2);
+ if (i < this.threshold) {
+ friendlyByteBuf.writeVarInt(0);
+ friendlyByteBuf.writeBytes(byteBuf);
+ } else {
++ // Paper start
++ if (this.deflater != null) {
+ byte[] bs = new byte[i];
+ byteBuf.readBytes(bs);
+ friendlyByteBuf.writeVarInt(bs.length);
+@@ -34,10 +49,48 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
+ }
+
+ this.deflater.reset();
++ return;
++ }
++
++ friendlyByteBuf.writeVarInt(i);
++ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf);
++ try {
++ this.compressor.deflate(compatibleIn, byteBuf2);
++ } finally {
++ compatibleIn.release();
++ }
++ // Paper end
+ }
+
+ }
+
++ // Paper start
++ @Override
++ protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception{
++ if (this.compressor != null) {
++ // We allocate bytes to be compressed plus 1 byte. This covers two cases:
++ //
++ // - Compression
++ // According to https://github.com/ebiggers/libdeflate/blob/master/libdeflate.h#L103,
++ // if the data compresses well (and we do not have some pathological case) then the maximum
++ // size the compressed size will ever be is the input size minus one.
++ // - Uncompressed
++ // This is fairly obvious - we will then have one more than the uncompressed size.
++ int initialBufferSize = msg.readableBytes() + 1;
++ return com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(ctx.alloc(), this.compressor, initialBufferSize);
++ }
++
++ return super.allocateBuffer(ctx, msg, preferDirect);
++ }
++
++ @Override
++ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
++ if (this.compressor != null) {
++ this.compressor.close();
++ }
++ }
++ // Paper end
++
+ public int getThreshold() {
+ return this.threshold;
+ }
+diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
+index d3a25cc5262843b5c9736ff32e300264d9847c9b..42400b6f0b693dd0ec4a2303a82bd131753a24ba 100644
+--- a/src/main/java/net/minecraft/network/Connection.java
++++ b/src/main/java/net/minecraft/network/Connection.java
+@@ -640,11 +640,28 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+ return networkmanager;
+ }
+
+- public void setEncryptionKey(Cipher decryptionCipher, Cipher encryptionCipher) {
+- this.encrypted = true;
+- this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher));
+- this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptionCipher));
++ // Paper start
++// public void setEncryptionKey(Cipher decryptionCipher, Cipher encryptionCipher) {
++// this.encrypted = true;
++// this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher));
++// this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptionCipher));
++// }
++
++ public void setupEncryption(javax.crypto.SecretKey key) throws net.minecraft.util.CryptException {
++ if (!this.encrypted) {
++ try {
++ com.velocitypowered.natives.encryption.VelocityCipher decryption = com.velocitypowered.natives.util.Natives.cipher.get().forDecryption(key);
++ com.velocitypowered.natives.encryption.VelocityCipher encryption = com.velocitypowered.natives.util.Natives.cipher.get().forEncryption(key);
++
++ this.encrypted = true;
++ this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryption));
++ this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryption));
++ } catch (java.security.GeneralSecurityException e) {
++ throw new net.minecraft.util.CryptException(e);
++ }
++ }
+ }
++ // Paper end
+
+ public boolean isEncrypted() {
+ return this.encrypted;
+@@ -673,16 +690,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+
+ public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) {
+ if (compressionThreshold >= 0) {
++ com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(-1); // Paper
+ if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
+ ((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(compressionThreshold, rejectsBadPackets);
+ } else {
+- this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressionThreshold, rejectsBadPackets));
++ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, rejectsBadPackets)); // Paper
+ }
+
+ if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) {
+ ((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(compressionThreshold);
+ } else {
+- this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressionThreshold));
++ this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressor, compressionThreshold)); // Paper
+ }
+ } else {
+ if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
+diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
+index bfa519b9335c960a5baec50b0da95d95cd5ee958..af4d9244102bd0ac204f44a8de7f3a7706e3692d 100644
+--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
+@@ -104,6 +104,11 @@ public class ServerConnectionListener {
+ ServerConnectionListener.LOGGER.info("Using default channel type");
+ }
+
++ // Paper start - indicate Velocity natives in use
++ ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity.");
++ ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity.");
++ // Paper end
++
+ this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer<Channel>() {
+ protected void initChannel(Channel channel) {
+ try {
+diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+index 4e23e9ac3579dd0cedf0dfdbb231f6fae111745c..4cd92875d60c2f1dcce67ac99e9ba257a10f87b1 100644
+--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+@@ -279,12 +279,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
+ }
+
+ SecretKey secretkey = packet.getSecretKey(privatekey);
+- Cipher cipher = Crypt.getCipher(2, secretkey);
+- Cipher cipher1 = Crypt.getCipher(1, secretkey);
++ // Paper start
++// Cipher cipher = Crypt.getCipher(2, secretkey);
++// Cipher cipher1 = Crypt.getCipher(1, secretkey);
++ // Paper end
+
+ s = (new BigInteger(Crypt.digestData("", this.server.getKeyPair().getPublic(), secretkey))).toString(16);
+ this.state = ServerLoginPacketListenerImpl.State.AUTHENTICATING;
+- this.connection.setEncryptionKey(cipher, cipher1);
++ this.connection.setupEncryption(secretkey); // Paper
+ } catch (CryptException cryptographyexception) {
+ throw new IllegalStateException("Protocol error", cryptographyexception);
+ }