diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/TlsExtension.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/TlsExtension.java index 569bc91..eaca4f7 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/TlsExtension.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/TlsExtension.java @@ -1,17 +1,29 @@ package ru.serega6531.packmate.service.optimization.tls.extensions; +import org.pcap4j.util.ByteArrays; +import ru.serega6531.packmate.service.optimization.tls.extensions.keyshare.KeyShareExtension; import ru.serega6531.packmate.service.optimization.tls.numbers.ExtensionType; -public class TlsExtension { +public abstract class TlsExtension { - private ExtensionType type; - private short length; - private byte[] data; // TODO create packets for each extension + protected ExtensionType type; + protected short extensionLength; - public TlsExtension(ExtensionType type, short length, byte[] data) { + public static TlsExtension newInstance(ExtensionType type, byte[] rawData, int offset, short extensionLength) { + if (extensionLength > 0) { + ByteArrays.validateBounds(rawData, offset, extensionLength); + } + + if (type == ExtensionType.KEY_SHARE) { + return new KeyShareExtension(type, rawData, offset, extensionLength); + } else { + return new UnimplementedTlsExtension(type, rawData, offset, extensionLength); + } + } + + public TlsExtension(ExtensionType type, short extensionLength) { this.type = type; - this.length = length; - this.data = data; + this.extensionLength = extensionLength; } public ExtensionType getType() { @@ -19,19 +31,11 @@ public class TlsExtension { } public short getLength() { - return length; - } - - public byte[] getData() { - return data; + return extensionLength; } @Override public String toString() { - if (data.length == 0) { - return type.name(); - } - - return type.name() + " [" + data.length + " bytes]"; + return type.name(); } } diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/UnimplementedTlsExtension.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/UnimplementedTlsExtension.java new file mode 100644 index 0000000..4576eef --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/UnimplementedTlsExtension.java @@ -0,0 +1,20 @@ +package ru.serega6531.packmate.service.optimization.tls.extensions; + +import ru.serega6531.packmate.service.optimization.tls.numbers.ExtensionType; + +public class UnimplementedTlsExtension extends TlsExtension { + + private byte[] data; + + public UnimplementedTlsExtension(ExtensionType type, byte[] rawData, int offset, short extensionLength) { + super(type, extensionLength); + + data = new byte[extensionLength]; + System.arraycopy(rawData, offset, data, 0, extensionLength); + } + + @Override + public String toString() { + return type.name() + "[" + extensionLength + " bytes]"; + } +} diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/keyshare/KeyShareEntry.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/keyshare/KeyShareEntry.java new file mode 100644 index 0000000..6a12095 --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/keyshare/KeyShareEntry.java @@ -0,0 +1,33 @@ +package ru.serega6531.packmate.service.optimization.tls.extensions.keyshare; + +import org.pcap4j.util.ByteArrays; +import ru.serega6531.packmate.service.optimization.tls.numbers.KeyGroup; + +import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; + +public class KeyShareEntry { + + private static final int GROUP_OFFSET = 0; + private static final int KEY_EXHANGE_LENGTH_OFFSET = GROUP_OFFSET + SHORT_SIZE_IN_BYTES; + private static final int KEY_EXCHANGE_OFFSET = KEY_EXHANGE_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; + + private KeyGroup group; + private short keyExhangeLength; + private byte[] keyExchange; + + public KeyShareEntry(byte[] rawData, int offset) { + this.group = KeyGroup.getInstance(ByteArrays.getShort(rawData, GROUP_OFFSET + offset)); + this.keyExhangeLength = ByteArrays.getShort(rawData, KEY_EXHANGE_LENGTH_OFFSET + offset); + keyExchange = new byte[keyExhangeLength]; + System.arraycopy(rawData, KEY_EXCHANGE_OFFSET + offset, keyExchange, 0, keyExhangeLength); + } + + public int size() { + return SHORT_SIZE_IN_BYTES + SHORT_SIZE_IN_BYTES + keyExhangeLength; + } + + @Override + public String toString() { + return group.name(); + } +} diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/keyshare/KeyShareExtension.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/keyshare/KeyShareExtension.java new file mode 100644 index 0000000..599be06 --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/extensions/keyshare/KeyShareExtension.java @@ -0,0 +1,39 @@ +package ru.serega6531.packmate.service.optimization.tls.extensions.keyshare; + +import org.pcap4j.util.ByteArrays; +import ru.serega6531.packmate.service.optimization.tls.extensions.TlsExtension; +import ru.serega6531.packmate.service.optimization.tls.numbers.ExtensionType; + +import java.util.ArrayList; +import java.util.List; + +import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; + +public class KeyShareExtension extends TlsExtension { + + private static final int KEY_SHARE_LENGTH_OFFSET = 0; + private static final int KEY_SHARE_ENTRY_OFFSET = KEY_SHARE_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; + + private short keyShareLength; + private List entries = new ArrayList<>(); + + public KeyShareExtension(ExtensionType type, byte[] rawData, int offset, short extensionLength) { + super(type, extensionLength); + + this.keyShareLength = ByteArrays.getShort(rawData, KEY_SHARE_LENGTH_OFFSET + offset); // the field is not always there + ByteArrays.validateBounds(rawData, KEY_SHARE_ENTRY_OFFSET + offset, keyShareLength); + + int cursor = KEY_SHARE_ENTRY_OFFSET + offset; + + while (cursor < offset + this.keyShareLength) { + KeyShareEntry entry = new KeyShareEntry(rawData, cursor); + entries.add(entry); + cursor += entry.size(); + } + } + + @Override + public String toString() { + return type.name() + " " + entries.toString(); + } +} diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/HandshakeType.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/HandshakeType.java index 7a52312..5e02c67 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/HandshakeType.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/HandshakeType.java @@ -5,6 +5,7 @@ import org.pcap4j.packet.namednumber.NamedNumber; import java.util.HashMap; import java.util.Map; +@SuppressWarnings("unused") public class HandshakeType extends NamedNumber { private static final Map registry = new HashMap<>(); diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/KeyGroup.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/KeyGroup.java new file mode 100644 index 0000000..a278abe --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/KeyGroup.java @@ -0,0 +1,98 @@ +package ru.serega6531.packmate.service.optimization.tls.numbers; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("unused") +public class KeyGroup extends NamedNumber { + + // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml + + private static final Map registry = new HashMap<>(); + + public static final KeyGroup RESERVED_GREASE_0 = new KeyGroup((short) 0, "Reserved (GREASE)"); + public static final KeyGroup SECT163K1 = new KeyGroup((short) 1, "sect163k1"); + public static final KeyGroup SECT163R1 = new KeyGroup((short) 2, "sect163r1"); + public static final KeyGroup SECT163R2 = new KeyGroup((short) 3, "sect163r2"); + public static final KeyGroup SECT193R1 = new KeyGroup((short) 4, "sect193r1"); + public static final KeyGroup SECT193R2 = new KeyGroup((short) 5, "sect193r2"); + public static final KeyGroup SECT233K1 = new KeyGroup((short) 6, "sect233k1"); + public static final KeyGroup SECT233R1 = new KeyGroup((short) 7, "sect233r1"); + public static final KeyGroup SECT239K1 = new KeyGroup((short) 8, "sect239k1"); + public static final KeyGroup SECT283K1 = new KeyGroup((short) 9, "sect283k1"); + public static final KeyGroup SECT283R1 = new KeyGroup((short) 10, "sect283r1"); + public static final KeyGroup SECT409K1 = new KeyGroup((short) 11, "sect409k1"); + public static final KeyGroup SECT409R1 = new KeyGroup((short) 12, "sect409r1"); + public static final KeyGroup SECT571K1 = new KeyGroup((short) 13, "sect571k1"); + public static final KeyGroup SECT571R1 = new KeyGroup((short) 14, "sect571r1"); + public static final KeyGroup SECP160K1 = new KeyGroup((short) 15, "secp160k1"); + public static final KeyGroup SECP160R1 = new KeyGroup((short) 16, "secp160r1"); + public static final KeyGroup SECP160R2 = new KeyGroup((short) 17, "secp160r2"); + public static final KeyGroup SECP192K1 = new KeyGroup((short) 18, "secp192k1"); + public static final KeyGroup SECP192R1 = new KeyGroup((short) 19, "secp192r1"); + public static final KeyGroup SECP224K1 = new KeyGroup((short) 20, "secp224k1"); + public static final KeyGroup SECP224R1 = new KeyGroup((short) 21, "secp224r1"); + public static final KeyGroup SECP256K1 = new KeyGroup((short) 22, "secp256k1"); + public static final KeyGroup SECP256R1 = new KeyGroup((short) 23, "secp256r1"); + public static final KeyGroup SECP384R1 = new KeyGroup((short) 24, "secp384r1"); + public static final KeyGroup SECP521R1 = new KeyGroup((short) 25, "secp521r1"); + public static final KeyGroup BRAINPOOLP256R1 = new KeyGroup((short) 26, "brainpoolP256r1"); + public static final KeyGroup BRAINPOOLP384R1 = new KeyGroup((short) 27, "brainpoolP384r1"); + public static final KeyGroup BRAINPOOLP512R1 = new KeyGroup((short) 28, "brainpoolP512r1"); + public static final KeyGroup X25519 = new KeyGroup((short) 29, "x25519"); + public static final KeyGroup X448 = new KeyGroup((short) 30, "x448"); + public static final KeyGroup BRAINPOOLP256R1TLS13 = new KeyGroup((short) 31, "brainpoolP256r1tls13"); + public static final KeyGroup BRAINPOOLP384R1TLS13 = new KeyGroup((short) 32, "brainpoolP384r1tls13"); + public static final KeyGroup BRAINPOOLP512R1TLS13 = new KeyGroup((short) 33, "brainpoolP512r1tls13"); + public static final KeyGroup GC256A = new KeyGroup((short) 34, "GC256A"); + public static final KeyGroup GC256B = new KeyGroup((short) 35, "GC256B"); + public static final KeyGroup GC256C = new KeyGroup((short) 36, "GC256C"); + public static final KeyGroup GC256D = new KeyGroup((short) 37, "GC256D"); + public static final KeyGroup GC512A = new KeyGroup((short) 38, "GC512A"); + public static final KeyGroup GC512B = new KeyGroup((short) 39, "GC512B"); + public static final KeyGroup GC512C = new KeyGroup((short) 40, "GC512C"); + public static final KeyGroup CURVESM2 = new KeyGroup((short) 41, "curveSM2"); + public static final KeyGroup FFDHE2048 = new KeyGroup((short) 256, "ffdhe2048"); + public static final KeyGroup FFDHE3072 = new KeyGroup((short) 257, "ffdhe3072"); + public static final KeyGroup FFDHE4096 = new KeyGroup((short) 258, "ffdhe4096"); + public static final KeyGroup FFDHE6144 = new KeyGroup((short) 259, "ffdhe6144"); + public static final KeyGroup FFDHE8192 = new KeyGroup((short) 260, "ffdhe8192"); + public static final KeyGroup RESERVED_GREASE_2570 = new KeyGroup((short) 2570, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_6682 = new KeyGroup((short) 6682, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_10794 = new KeyGroup((short) 10794, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_14906 = new KeyGroup((short) 14906, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_19018 = new KeyGroup((short) 19018, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_23130 = new KeyGroup((short) 23130, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_27242 = new KeyGroup((short) 27242, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_31354 = new KeyGroup((short) 31354, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_35466 = new KeyGroup((short) 35466, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_39578 = new KeyGroup((short) 39578, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_43690 = new KeyGroup((short) 43690, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_47802 = new KeyGroup((short) 47802, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_51914 = new KeyGroup((short) 51914, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_56026 = new KeyGroup((short) 56026, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_60138 = new KeyGroup((short) 60138, "Reserved (GREASE)"); + public static final KeyGroup RESERVED_GREASE_64250 = new KeyGroup((short) 64250, "Reserved (GREASE)"); + public static final KeyGroup ARBITRARY_EXPLICIT_PRIME_CURVES = new KeyGroup((short) 65281, "arbitrary_explicit_prime_curves"); + public static final KeyGroup ARBITRARY_EXPLICIT_CHAR2_CURVES = new KeyGroup((short) 65282, "arbitrary_explicit_char2_curves"); + + public KeyGroup(Short value, String name) { + super(value, name); + registry.put(value, this); + } + + public static KeyGroup getInstance(Short value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + return new KeyGroup(value, "Unknown"); + } + } + + @Override + public int compareTo(KeyGroup o) { + return value().compareTo(o.value()); + } +} diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/HelloHandshakeRecordContent.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/HelloHandshakeRecordContent.java index b892ef2..82cfd7a 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/HelloHandshakeRecordContent.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/HelloHandshakeRecordContent.java @@ -49,10 +49,7 @@ public abstract class HelloHandshakeRecordContent implements HandshakeRecordCont short extensionLength = ByteArrays.getShort(rawData, cursor); cursor += SHORT_SIZE_IN_BYTES; - byte[] extensionData = new byte[extensionLength]; - System.arraycopy(rawData, cursor, extensionData, 0, extensionLength); - - extensions.add(new TlsExtension(extensionType, extensionLength, extensionData)); + extensions.add(TlsExtension.newInstance(extensionType, rawData, cursor, extensionLength)); cursor += extensionLength; }