diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/ContentType.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/ContentType.java index 3038add..11f0e80 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/ContentType.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/ContentType.java @@ -7,10 +7,13 @@ import java.util.Map; public class ContentType extends NamedNumber { + // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml + public static final ContentType CHANGE_CIPHER_SPEC = new ContentType((byte) 20, "Change Cipher Spec"); public static final ContentType ALERT = new ContentType((byte) 21, "Alert"); public static final ContentType HANDSHAKE = new ContentType((byte) 22, "Handshake"); public static final ContentType APPLICATION_DATA = new ContentType((byte) 23, "Application Data"); + public static final ContentType HEARTBEAT = new ContentType((byte) 24, "Heartbeat"); private static final Map registry = new HashMap<>(); 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 92c3120..7a52312 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 @@ -7,9 +7,18 @@ import java.util.Map; public class HandshakeType extends NamedNumber { + private static final Map registry = new HashMap<>(); + + // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml + public static final HandshakeType HELLO_REQUEST = new HandshakeType((byte) 0, "Hello Request"); public static final HandshakeType CLIENT_HELLO = new HandshakeType((byte) 1, "Client Hello"); public static final HandshakeType SERVER_HELLO = new HandshakeType((byte) 2, "Server Hello"); + public static final HandshakeType HELLO_VERIFY_REQUEST = new HandshakeType((byte) 3, "Hello Verify Request"); + public static final HandshakeType NEW_SESSION_TICKET = new HandshakeType((byte) 4, "New Session Ticket"); + public static final HandshakeType END_OF_EARLY_DATA = new HandshakeType((byte) 5, "End Of Early Data"); + public static final HandshakeType HELLO_RETRY_REQUEST = new HandshakeType((byte) 6, "Hello Retry Request"); + public static final HandshakeType ENCRYPTED_EXTENSIONS = new HandshakeType((byte) 8, "Encrypted Extensions"); public static final HandshakeType CERTIFICATE = new HandshakeType((byte) 11, "Certificate"); public static final HandshakeType SERVER_KEY_EXCHANGE = new HandshakeType((byte) 12, "Server Key Excange"); public static final HandshakeType CERTIFICATE_REQUEST = new HandshakeType((byte) 13, "Certificate Request"); @@ -17,24 +26,16 @@ public class HandshakeType extends NamedNumber { public static final HandshakeType CERTIFICATE_VERIFY = new HandshakeType((byte) 15, "Certificate Verify"); public static final HandshakeType CLIENT_KEY_EXCHANGE = new HandshakeType((byte) 16, "Client Key Exchange"); public static final HandshakeType FINISHED = new HandshakeType((byte) 20, "Finished"); - - private static final Map registry = new HashMap<>(); - - static { - registry.put(HELLO_REQUEST.value(), HELLO_REQUEST); - registry.put(CLIENT_HELLO.value(), CLIENT_HELLO); - registry.put(SERVER_HELLO.value(), SERVER_HELLO); - registry.put(CERTIFICATE.value(), CERTIFICATE); - registry.put(SERVER_KEY_EXCHANGE.value(), SERVER_KEY_EXCHANGE); - registry.put(CERTIFICATE_REQUEST.value(), CERTIFICATE_REQUEST); - registry.put(SERVER_HELLO_DONE.value(), SERVER_HELLO_DONE); - registry.put(CERTIFICATE_VERIFY.value(), CERTIFICATE_VERIFY); - registry.put(CLIENT_KEY_EXCHANGE.value(), CLIENT_KEY_EXCHANGE); - registry.put(FINISHED.value(), FINISHED); - } + public static final HandshakeType CERTIFICATE_URL = new HandshakeType((byte) 21, "Certificate URL"); + public static final HandshakeType CERTIFICATE_STATUS = new HandshakeType((byte) 22, "Certificate Status"); + public static final HandshakeType SUPPLEMENTAL_DATA = new HandshakeType((byte) 23, "Supplemental Data"); + public static final HandshakeType KEY_UPDATE = new HandshakeType((byte) 24, "Key Update"); + public static final HandshakeType COMPRESSED_CERTIFICATE = new HandshakeType((byte) 25, "Compressed Certificate"); + public static final HandshakeType MESSAGE_HASH = new HandshakeType((byte) 254, "Message Hash"); public HandshakeType(Byte value, String name) { super(value, name); + registry.put(value, this); } public static HandshakeType getInstance(Byte value) { diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/HandshakeRecord.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/HandshakeRecord.java index 4a493ff..4e23879 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/HandshakeRecord.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/HandshakeRecord.java @@ -5,15 +5,19 @@ import ru.serega6531.packmate.service.optimization.tls.numbers.HandshakeType; import ru.serega6531.packmate.service.optimization.tls.records.handshakes.ClientHelloHandshakeRecordContent; import ru.serega6531.packmate.service.optimization.tls.records.handshakes.HandshakeRecordContent; import ru.serega6531.packmate.service.optimization.tls.records.handshakes.ServerHelloHandshakeRecordContent; +import ru.serega6531.packmate.service.optimization.tls.records.handshakes.UnknownRecordContent; +import ru.serega6531.packmate.utils.BytesUtils; import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; public class HandshakeRecord extends TlsRecord { private static final int HANDSHAKE_TYPE_OFFSET = 0; - private static final int CONTENT_OFFSET = HANDSHAKE_TYPE_OFFSET + BYTE_SIZE_IN_BYTES; + private static final int LENGTH_OFFSET = HANDSHAKE_TYPE_OFFSET + BYTE_SIZE_IN_BYTES; + private static final int CONTENT_OFFSET = LENGTH_OFFSET + 3; private HandshakeType handshakeType; + private int handshakeLength; // 3 bytes private HandshakeRecordContent content; public static HandshakeRecord newInstance(byte[] rawData, int offset, int length) { @@ -22,37 +26,24 @@ public class HandshakeRecord extends TlsRecord { private HandshakeRecord(byte[] rawData, int offset, int length) { this.handshakeType = HandshakeType.getInstance(ByteArrays.getByte(rawData, HANDSHAKE_TYPE_OFFSET + offset)); + this.handshakeLength = BytesUtils.getThreeBytesInt(rawData, LENGTH_OFFSET + offset); - if (handshakeType == HandshakeType.HELLO_REQUEST) { - - } else if (handshakeType == HandshakeType.CLIENT_HELLO) { + if (handshakeType == HandshakeType.CLIENT_HELLO) { this.content = ClientHelloHandshakeRecordContent.newInstance( - rawData, offset + CONTENT_OFFSET); + rawData, offset + CONTENT_OFFSET, handshakeLength); } else if (handshakeType == HandshakeType.SERVER_HELLO) { this.content = ServerHelloHandshakeRecordContent.newInstance( - rawData, offset + CONTENT_OFFSET); - } else if (handshakeType == HandshakeType.CERTIFICATE) { - - } else if (handshakeType == HandshakeType.SERVER_KEY_EXCHANGE) { - - } else if (handshakeType == HandshakeType.CERTIFICATE_REQUEST) { - - } else if (handshakeType == HandshakeType.SERVER_HELLO_DONE) { - - } else if (handshakeType == HandshakeType.CERTIFICATE_VERIFY) { - - } else if (handshakeType == HandshakeType.CLIENT_KEY_EXCHANGE) { - - } else if (handshakeType == HandshakeType.FINISHED) { - + rawData, offset + CONTENT_OFFSET, handshakeLength); } else { - throw new IllegalArgumentException("Unknown handshake type " + handshakeType); + this.content = UnknownRecordContent.newInstance( + rawData, offset + CONTENT_OFFSET, handshakeLength); } } @Override public String toString() { - return " Handshake type: " + handshakeType + "\n" + + return " Handshake length: " + handshakeLength + "\n" + + " Handshake type: " + handshakeType + "\n" + content.toString(); } } diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/ClientHelloHandshakeRecordContent.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/ClientHelloHandshakeRecordContent.java index 3e355a1..b083220 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/ClientHelloHandshakeRecordContent.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/ClientHelloHandshakeRecordContent.java @@ -27,7 +27,8 @@ public class ClientHelloHandshakeRecordContent extends HelloHandshakeRecordConte private byte compressionMethodsLength; private List compressionMethods; - public static ClientHelloHandshakeRecordContent newInstance(byte[] rawData, int offset) { + public static ClientHelloHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); return new ClientHelloHandshakeRecordContent(rawData, offset); } 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 669304d..b892ef2 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 @@ -4,7 +4,6 @@ import org.pcap4j.util.ByteArrays; import ru.serega6531.packmate.service.optimization.tls.extensions.TlsExtension; import ru.serega6531.packmate.service.optimization.tls.numbers.ExtensionType; import ru.serega6531.packmate.service.optimization.tls.numbers.TlsVersion; -import ru.serega6531.packmate.utils.BytesUtils; import java.util.ArrayList; import java.util.List; @@ -14,13 +13,11 @@ import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; public abstract class HelloHandshakeRecordContent implements HandshakeRecordContent { - private static final int LENGTH_OFFSET = 0; - private static final int VERSION_OFFSET = LENGTH_OFFSET + 3; + private static final int VERSION_OFFSET = 0; private static final int RANDOM_OFFSET = VERSION_OFFSET + SHORT_SIZE_IN_BYTES; private static final int SESSION_ID_LENGTH_OFFSET = RANDOM_OFFSET + 32; protected static final int SESSION_ID_OFFSET = SESSION_ID_LENGTH_OFFSET + BYTE_SIZE_IN_BYTES; - protected int length; // 3 bytes protected TlsVersion version; protected byte[] random = new byte[32]; protected byte sessionIdLength; @@ -30,7 +27,6 @@ public abstract class HelloHandshakeRecordContent implements HandshakeRecordCont private List extensions; protected void readCommonPart(byte[] rawData, int offset) { - this.length = BytesUtils.getThreeBytesInt(rawData, LENGTH_OFFSET + offset); this.version = TlsVersion.getInstance(ByteArrays.getShort(rawData, VERSION_OFFSET + offset)); System.arraycopy(rawData, RANDOM_OFFSET + offset, random, 0, 32); this.sessionIdLength = ByteArrays.getByte(rawData, SESSION_ID_LENGTH_OFFSET + offset); @@ -64,8 +60,7 @@ public abstract class HelloHandshakeRecordContent implements HandshakeRecordCont @Override public String toString() { - return " Handshake length: " + length + "\n" + - " TLS version: " + version + "\n" + + return " TLS version: " + version + "\n" + " Client random: " + ByteArrays.toHexString(random, "") + "\n" + " Session id: " + (sessionIdLength > 0 ? ByteArrays.toHexString(sessionId, "") : "null") + "\n" + " Extensions: " + extensions.toString(); diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/ServerHelloHandshakeRecordContent.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/ServerHelloHandshakeRecordContent.java index 5eb0e10..1e9ca29 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/ServerHelloHandshakeRecordContent.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/ServerHelloHandshakeRecordContent.java @@ -17,7 +17,8 @@ public class ServerHelloHandshakeRecordContent extends HelloHandshakeRecordConte private CipherSuite cipherSuite; private CompressionMethod compressionMethod; - public static ServerHelloHandshakeRecordContent newInstance(byte[] rawData, int offset) { + public static ServerHelloHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); return new ServerHelloHandshakeRecordContent(rawData, offset); } diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/UnknownRecordContent.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/UnknownRecordContent.java new file mode 100644 index 0000000..848aeab --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/handshakes/UnknownRecordContent.java @@ -0,0 +1,22 @@ +package ru.serega6531.packmate.service.optimization.tls.records.handshakes; + +import org.pcap4j.util.ByteArrays; + +public class UnknownRecordContent implements HandshakeRecordContent { + + private byte[] content; + + public static UnknownRecordContent newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); + return new UnknownRecordContent(rawData, offset, length); + } + + public UnknownRecordContent(byte[] rawData, int offset, int length) { + System.arraycopy(rawData, offset, content, 0, length); + } + + @Override + public String toString() { + return " [" + content.length + " bytes]"; + } +}