From 273b2be4424f1d4915c7e9dc5cee0c85c62d4c75 Mon Sep 17 00:00:00 2001 From: serega6531 Date: Tue, 28 Apr 2020 15:58:34 +0300 Subject: [PATCH 01/10] TLS packets parsing --- .../java/org/pcap4j/packet/TlsPacket.java | 169 ++++ .../namednumber/tls/AlertDescription.java | 67 ++ .../packet/namednumber/tls/AlertLevel.java | 34 + .../packet/namednumber/tls/CipherSuite.java | 741 ++++++++++++++++++ .../namednumber/tls/CompressionMethod.java | 38 + .../packet/namednumber/tls/ContentType.java | 44 ++ .../packet/namednumber/tls/ExtensionType.java | 98 +++ .../packet/namednumber/tls/HandshakeType.java | 52 ++ .../namednumber/tls/HeartbeatMessageType.java | 33 + .../packet/namednumber/tls/KeyGroup.java | 98 +++ .../packet/namednumber/tls/TlsVersion.java | 41 + .../packet/tls/extensions/TlsExtension.java | 49 ++ .../extensions/UnimplementedTlsExtension.java | 24 + .../keyshare/ClientKeyShareExtension.java | 23 + .../extensions/keyshare/KeyShareEntry.java | 33 + .../keyshare/KeyShareExtension.java | 46 ++ .../keyshare/ServerKeyShareExtension.java | 14 + .../packet/tls/keys/DhClientParams.java | 42 + .../packet/tls/keys/EcdheServerParams.java | 44 ++ .../pcap4j/packet/tls/keys/TlsKeyUtils.java | 108 +++ .../packet/tls/keys/enums/CurveType.java | 16 + .../packet/tls/keys/enums/NamedCurve.java | 57 ++ .../tls/keys/enums/SignatureScheme.java | 58 ++ .../packet/tls/records/AlertRecord.java | 37 + .../tls/records/ApplicationDataRecord.java | 33 + .../tls/records/ChangeCipherSpecRecord.java | 27 + .../packet/tls/records/HandshakeRecord.java | 72 ++ .../packet/tls/records/HeartbeatRecord.java | 53 ++ .../pcap4j/packet/tls/records/TlsRecord.java | 7 + .../BasicHandshakeRecordContent.java | 36 + .../CertificateHandshakeRecordContent.java | 51 ++ .../ClientHelloHandshakeRecordContent.java | 82 ++ .../handshakes/HandshakeRecordContent.java | 4 + .../HelloHandshakeRecordContent.java | 81 ++ .../ServerHelloHandshakeRecordContent.java | 64 ++ .../main/java/org/pcap4j/util/ByteArrays.java | 33 + 36 files changed, 2509 insertions(+) create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertDescription.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CipherSuite.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CompressionMethod.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ContentType.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ExtensionType.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HandshakeType.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HeartbeatMessageType.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/KeyGroup.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/TlsVersion.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/DhClientParams.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/EcdheServerParams.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/TlsKeyUtils.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/CurveType.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/NamedCurve.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/SignatureScheme.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/TlsRecord.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java create mode 100644 pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java new file mode 100644 index 000000000..0873ee76e --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java @@ -0,0 +1,169 @@ +package org.pcap4j.packet; + +import org.pcap4j.packet.namednumber.tls.ContentType; +import org.pcap4j.packet.namednumber.tls.TlsVersion; +import org.pcap4j.packet.tls.records.*; +import org.pcap4j.util.ByteArrays; + +import java.util.ArrayList; +import java.util.List; + +import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; +import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; + +public class TlsPacket extends AbstractPacket { + + private final TlsPacket.TlsHeader header; + private final Packet payload; + + public static TlsPacket newPacket(byte[] rawData, int offset, int length) throws IllegalRawDataException { + ByteArrays.validateBounds(rawData, offset, length); + return new TlsPacket(rawData, offset, length); + } + + private TlsPacket(byte[] rawData, int offset, int length) throws IllegalRawDataException { + this.header = new TlsPacket.TlsHeader(rawData, offset, length); + + int payloadLength = length - header.length(); + if (payloadLength > 0) { + this.payload = TlsPacket.newPacket(rawData, offset + header.length(), payloadLength); + } else { + this.payload = null; + } + } + + private TlsPacket(TlsPacket.Builder builder) { + if (builder == null) { + throw new NullPointerException("builder: null"); + } + + this.payload = builder.payloadBuilder != null ? builder.payloadBuilder.build() : null; + this.header = new TlsPacket.TlsHeader(builder); + } + + @Override + public TlsHeader getHeader() { + return header; + } + + @Override + public Packet getPayload() { + return payload; + } + + @Override + public Builder getBuilder() { + return new Builder(this); + } + + @Override + protected String buildString() { + StringBuilder sb = new StringBuilder(getHeader().toString()); + + TlsPacket p = (TlsPacket) getPayload(); + + if (p != null) { + sb.append('\n'); + sb.append(p.toString()); + } + + return sb.toString(); + } + + public static final class TlsHeader extends AbstractHeader { + + /* + 0x0 - Content Type + 0x1 - Version + 0x3 - Length + 0x5 - Record content + */ + + private static final int CONTENT_TYPE_OFFSET = 0; + private static final int VERSION_OFFSET = CONTENT_TYPE_OFFSET + BYTE_SIZE_IN_BYTES; + private static final int LENGTH_OFFSET = VERSION_OFFSET + SHORT_SIZE_IN_BYTES; + private static final int RECORD_OFFSET = LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; + + private ContentType contentType; + private TlsVersion version; + private short recordLength; + private TlsRecord record; + + private TlsHeader(Builder builder) { + //TODO + } + + private TlsHeader(byte[] rawData, int offset, int length) throws IllegalRawDataException { + ByteArrays.validateBounds(rawData, offset, RECORD_OFFSET); + this.contentType = ContentType.getInstance(ByteArrays.getByte(rawData, CONTENT_TYPE_OFFSET + offset)); + this.version = TlsVersion.getInstance(ByteArrays.getShort(rawData, VERSION_OFFSET + offset)); + this.recordLength = ByteArrays.getShort(rawData, LENGTH_OFFSET + offset); + + if (contentType == ContentType.HANDSHAKE) { + this.record = HandshakeRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength); + } else if (contentType == ContentType.CHANGE_CIPHER_SPEC) { + this.record = ChangeCipherSpecRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength); + } else if (contentType == ContentType.APPLICATION_DATA) { + this.record = ApplicationDataRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength); + } else if (contentType == ContentType.ALERT) { + this.record = AlertRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength); + } else if (contentType == ContentType.HEARTBEAT) { + this.record = HeartbeatRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength); + } else { + throw new IllegalArgumentException("Unknown content type: " + contentType); + } + } + + public ContentType getContentType() { + return contentType; + } + + public TlsVersion getVersion() { + return version; + } + + public TlsRecord getRecord() { + return record; + } + + @Override + protected List getRawFields() { + List rawFields = new ArrayList<>(); + rawFields.add(new byte[]{contentType.value()}); + rawFields.add(ByteArrays.toByteArray(version.value())); + rawFields.add(ByteArrays.toByteArray(recordLength)); + //TODO + return rawFields; + } + + @Override + public int length() { + return RECORD_OFFSET + recordLength; + } + + @Override + protected String buildString() { + return "TLS Header [" + length() + " bytes]\n" + + " Version: " + version + "\n" + + " Type: " + contentType + "\n" + + record.toString(); + } + } + + public static final class Builder extends AbstractBuilder { + + private Packet.Builder payloadBuilder; + + public Builder() { + } + + public Builder(TlsPacket packet) { + this.payloadBuilder = packet.payload != null ? packet.payload.getBuilder() : null; + } + + @Override + public Packet build() { + return new TlsPacket(this); + } + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertDescription.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertDescription.java new file mode 100644 index 000000000..65abc043d --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertDescription.java @@ -0,0 +1,67 @@ +package org.pcap4j.packet.namednumber.tls; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +import java.util.Map; + +public class AlertDescription extends NamedNumber { + + private static final Map registry = new HashMap<>(); + + // https://techcommunity.microsoft.com/t5/iis-support-blog/ssl-tls-alert-protocol-and-the-alert-codes/ba-p/377132 + + public static AlertDescription close_notify = new AlertDescription((byte) 0, "close_notify"); + public static AlertDescription unexpected_message = new AlertDescription((byte) 10, "unexpected_message"); + public static AlertDescription bad_record_mac = new AlertDescription((byte) 20, "bad_record_mac"); + public static AlertDescription decryption_failed_RESERVED = new AlertDescription((byte) 21, "decryption_failed_RESERVED"); + public static AlertDescription record_overflow = new AlertDescription((byte) 22, "record_overflow"); + public static AlertDescription decompression_failure_RESERVED = new AlertDescription((byte) 30, "decompression_failure_RESERVED"); + public static AlertDescription handshake_failure = new AlertDescription((byte) 40, "handshake_failure"); + public static AlertDescription no_certificate_RESERVED = new AlertDescription((byte) 41, "no_certificate_RESERVED"); + public static AlertDescription bad_certificate = new AlertDescription((byte) 42, "bad_certificate"); + public static AlertDescription unsupported_certificate = new AlertDescription((byte) 43, "unsupported_certificate"); + public static AlertDescription certificate_revoked = new AlertDescription((byte) 44, "certificate_revoked"); + public static AlertDescription certificate_expired = new AlertDescription((byte) 45, "certificate_expired"); + public static AlertDescription certificate_unknown = new AlertDescription((byte) 46, "certificate_unknown"); + public static AlertDescription illegal_parameter = new AlertDescription((byte) 47, "illegal_parameter"); + public static AlertDescription unknown_ca = new AlertDescription((byte) 48, "unknown_ca"); + public static AlertDescription access_denied = new AlertDescription((byte) 49, "access_denied"); + public static AlertDescription decode_error = new AlertDescription((byte) 50, "decode_error"); + public static AlertDescription decrypt_error = new AlertDescription((byte) 51, "decrypt_error"); + public static AlertDescription export_restriction_RESERVED = new AlertDescription((byte) 60, "export_restriction_RESERVED"); + public static AlertDescription protocol_version = new AlertDescription((byte) 70, "protocol_version"); + public static AlertDescription insufficient_security = new AlertDescription((byte) 71, "insufficient_security"); + public static AlertDescription internal_error = new AlertDescription((byte) 80, "internal_error"); + public static AlertDescription inappropriate_fallback = new AlertDescription((byte) 86, "inappropriate_fallback"); + public static AlertDescription user_canceled = new AlertDescription((byte) 90, "user_canceled"); + public static AlertDescription no_renegotiation_RESERVED = new AlertDescription((byte) 100, "no_renegotiation_RESERVED"); + public static AlertDescription missing_extension = new AlertDescription((byte) 109, "missing_extension"); + public static AlertDescription unsupported_extension = new AlertDescription((byte) 110, "unsupported_extension"); + public static AlertDescription certificate_unobtainable_RESERVED = new AlertDescription((byte) 111, "certificate_unobtainable_RESERVED"); + public static AlertDescription unrecognized_name = new AlertDescription((byte) 112, "unrecognized_name"); + public static AlertDescription bad_certificate_status_response = new AlertDescription((byte) 113, "bad_certificate_status_response"); + public static AlertDescription bad_certificate_hash_value_RESERVED = new AlertDescription((byte) 114, "bad_certificate_hash_value_RESERVED"); + public static AlertDescription unknown_psk_identity = new AlertDescription((byte) 115, "unknown_psk_identity"); + public static AlertDescription certificate_required = new AlertDescription((byte) 116, "certificate_required"); + public static AlertDescription no_application_protocol = new AlertDescription((byte) 120, "no_application_protocol"); + + public AlertDescription(Byte value, String name) { + super(value, name); + registry.put(value, this); + } + + public static AlertDescription getInstance(Byte value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + throw new IllegalArgumentException("Unknown alert description: " + value); + } + } + + @Override + public int compareTo(AlertDescription o) { + return value().compareTo(o.value()); + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java new file mode 100644 index 000000000..43ff234d0 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java @@ -0,0 +1,34 @@ +package org.pcap4j.packet.namednumber.tls; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("unused") +public class AlertLevel extends NamedNumber { + + private static final Map registry = new HashMap<>(); + + public static final AlertLevel WARNING = new AlertLevel((byte) 1, "warning"); + public static final AlertLevel FATAL = new AlertLevel((byte) 2, "fatal"); + + public AlertLevel(Byte value, String name) { + super(value, name); + registry.put(value, this); + } + + public static AlertLevel getInstance(Byte value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + throw new IllegalArgumentException("Unknown alert level: " + value); + } + } + + @Override + public int compareTo(AlertLevel o) { + return value().compareTo(o.value()); + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CipherSuite.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CipherSuite.java new file mode 100644 index 000000000..69fa6b2fa --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CipherSuite.java @@ -0,0 +1,741 @@ +package org.pcap4j.packet.namednumber.tls; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("unused") +public class CipherSuite extends NamedNumber { + + private static final Map registry = new HashMap<>(); + + // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml + + public static final CipherSuite TLS_NULL_WITH_NULL_NULL = + new CipherSuite((short) 0x0000, "TLS_NULL_WITH_NULL_NULL"); + public static final CipherSuite TLS_RSA_WITH_NULL_MD5 = + new CipherSuite((short) 0x0001, "TLS_RSA_WITH_NULL_MD5"); + public static final CipherSuite TLS_RSA_WITH_NULL_SHA = + new CipherSuite((short) 0x0002, "TLS_RSA_WITH_NULL_SHA"); + public static final CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5 = + new CipherSuite((short) 0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"); + public static final CipherSuite TLS_RSA_WITH_RC4_128_MD5 = + new CipherSuite((short) 0x0004, "TLS_RSA_WITH_RC4_128_MD5"); + public static final CipherSuite TLS_RSA_WITH_RC4_128_SHA = + new CipherSuite((short) 0x0005, "TLS_RSA_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = + new CipherSuite((short) 0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"); + public static final CipherSuite TLS_RSA_WITH_IDEA_CBC_SHA = + new CipherSuite((short) 0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA"); + public static final CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = + new CipherSuite((short) 0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"); + public static final CipherSuite TLS_RSA_WITH_DES_CBC_SHA = + new CipherSuite((short) 0x0009, "TLS_RSA_WITH_DES_CBC_SHA"); + public static final CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x000A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = + new CipherSuite((short) 0x000B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"); + public static final CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA = + new CipherSuite((short) 0x000C, "TLS_DH_DSS_WITH_DES_CBC_SHA"); + public static final CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x000D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = + new CipherSuite((short) 0x000E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"); + public static final CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA = + new CipherSuite((short) 0x000F, "TLS_DH_RSA_WITH_DES_CBC_SHA"); + public static final CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = + new CipherSuite((short) 0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"); + public static final CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA = + new CipherSuite((short) 0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA"); + public static final CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = + new CipherSuite((short) 0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"); + public static final CipherSuite TLS_DHE_RSA_WITH_DES_CBC_SHA = + new CipherSuite((short) 0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA"); + public static final CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = + new CipherSuite((short) 0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"); + public static final CipherSuite TLS_DH_anon_WITH_RC4_128_MD5 = + new CipherSuite((short) 0x0018, "TLS_DH_anon_WITH_RC4_128_MD5"); + public static final CipherSuite TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = + new CipherSuite((short) 0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"); + public static final CipherSuite TLS_DH_anon_WITH_DES_CBC_SHA = + new CipherSuite((short) 0x001A, "TLS_DH_anon_WITH_DES_CBC_SHA"); + public static final CipherSuite TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x001B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_KRB5_WITH_DES_CBC_SHA = + new CipherSuite((short) 0x001E, "TLS_KRB5_WITH_DES_CBC_SHA"); + public static final CipherSuite TLS_KRB5_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x001F, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_KRB5_WITH_RC4_128_SHA = + new CipherSuite((short) 0x0020, "TLS_KRB5_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_KRB5_WITH_IDEA_CBC_SHA = + new CipherSuite((short) 0x0021, "TLS_KRB5_WITH_IDEA_CBC_SHA"); + public static final CipherSuite TLS_KRB5_WITH_DES_CBC_MD5 = + new CipherSuite((short) 0x0022, "TLS_KRB5_WITH_DES_CBC_MD5"); + public static final CipherSuite TLS_KRB5_WITH_3DES_EDE_CBC_MD5 = + new CipherSuite((short) 0x0023, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5"); + public static final CipherSuite TLS_KRB5_WITH_RC4_128_MD5 = + new CipherSuite((short) 0x0024, "TLS_KRB5_WITH_RC4_128_MD5"); + public static final CipherSuite TLS_KRB5_WITH_IDEA_CBC_MD5 = + new CipherSuite((short) 0x0025, "TLS_KRB5_WITH_IDEA_CBC_MD5"); + public static final CipherSuite TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA = + new CipherSuite((short) 0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"); + public static final CipherSuite TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA = + new CipherSuite((short) 0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"); + public static final CipherSuite TLS_KRB5_EXPORT_WITH_RC4_40_SHA = + new CipherSuite((short) 0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"); + public static final CipherSuite TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 = + new CipherSuite((short) 0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"); + public static final CipherSuite TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 = + new CipherSuite((short) 0x002A, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"); + public static final CipherSuite TLS_KRB5_EXPORT_WITH_RC4_40_MD5 = + new CipherSuite((short) 0x002B, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"); + public static final CipherSuite TLS_PSK_WITH_NULL_SHA = + new CipherSuite((short) 0x002C, "TLS_PSK_WITH_NULL_SHA"); + public static final CipherSuite TLS_DHE_PSK_WITH_NULL_SHA = + new CipherSuite((short) 0x002D, "TLS_DHE_PSK_WITH_NULL_SHA"); + public static final CipherSuite TLS_RSA_PSK_WITH_NULL_SHA = + new CipherSuite((short) 0x002E, "TLS_RSA_PSK_WITH_NULL_SHA"); + public static final CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_DH_DSS_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_DH_RSA_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_DH_anon_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_RSA_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_DH_DSS_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_DH_RSA_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_DH_anon_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_RSA_WITH_NULL_SHA256 = + new CipherSuite((short) 0x003B, "TLS_RSA_WITH_NULL_SHA256"); + public static final CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_RSA_WITH_AES_256_CBC_SHA256 = + new CipherSuite((short) 0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256"); + public static final CipherSuite TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = + new CipherSuite((short) 0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"); + public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = + new CipherSuite((short) 0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA"); + public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = + new CipherSuite((short) 0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA"); + public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = + new CipherSuite((short) 0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"); + public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = + new CipherSuite((short) 0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"); + public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = + new CipherSuite((short) 0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = + new CipherSuite((short) 0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"); + public static final CipherSuite TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = + new CipherSuite((short) 0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"); + public static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = + new CipherSuite((short) 0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = + new CipherSuite((short) 0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"); + public static final CipherSuite TLS_DH_anon_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0x006C, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_DH_anon_WITH_AES_256_CBC_SHA256 = + new CipherSuite((short) 0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"); + public static final CipherSuite TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = + new CipherSuite((short) 0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"); + public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = + new CipherSuite((short) 0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"); + public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = + new CipherSuite((short) 0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"); + public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = + new CipherSuite((short) 0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"); + public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = + new CipherSuite((short) 0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"); + public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = + new CipherSuite((short) 0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"); + public static final CipherSuite TLS_PSK_WITH_RC4_128_SHA = + new CipherSuite((short) 0x008A, "TLS_PSK_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_PSK_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_PSK_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0x008C, "TLS_PSK_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_PSK_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0x008D, "TLS_PSK_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_DHE_PSK_WITH_RC4_128_SHA = + new CipherSuite((short) 0x008E, "TLS_DHE_PSK_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x008F, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_DHE_PSK_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0x0090, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_DHE_PSK_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0x0091, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_RSA_PSK_WITH_RC4_128_SHA = + new CipherSuite((short) 0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_RSA_PSK_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0x0094, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_RSA_PSK_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0x0095, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_RSA_WITH_SEED_CBC_SHA = + new CipherSuite((short) 0x0096, "TLS_RSA_WITH_SEED_CBC_SHA"); + public static final CipherSuite TLS_DH_DSS_WITH_SEED_CBC_SHA = + new CipherSuite((short) 0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA"); + public static final CipherSuite TLS_DH_RSA_WITH_SEED_CBC_SHA = + new CipherSuite((short) 0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA"); + public static final CipherSuite TLS_DHE_DSS_WITH_SEED_CBC_SHA = + new CipherSuite((short) 0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA"); + public static final CipherSuite TLS_DHE_RSA_WITH_SEED_CBC_SHA = + new CipherSuite((short) 0x009A, "TLS_DHE_RSA_WITH_SEED_CBC_SHA"); + public static final CipherSuite TLS_DH_anon_WITH_SEED_CBC_SHA = + new CipherSuite((short) 0x009B, "TLS_DH_anon_WITH_SEED_CBC_SHA"); + public static final CipherSuite TLS_RSA_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_RSA_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_DH_anon_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x00A6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_DH_anon_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x00A7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_PSK_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x00A8, "TLS_PSK_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_PSK_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x00A9, "TLS_PSK_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x00AA, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x00AB, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x00AC, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x00AD, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_PSK_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0x00AE, "TLS_PSK_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_PSK_WITH_AES_256_CBC_SHA384 = + new CipherSuite((short) 0x00AF, "TLS_PSK_WITH_AES_256_CBC_SHA384"); + public static final CipherSuite TLS_PSK_WITH_NULL_SHA256 = + new CipherSuite((short) 0x00B0, "TLS_PSK_WITH_NULL_SHA256"); + public static final CipherSuite TLS_PSK_WITH_NULL_SHA384 = + new CipherSuite((short) 0x00B1, "TLS_PSK_WITH_NULL_SHA384"); + public static final CipherSuite TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0x00B2, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = + new CipherSuite((short) 0x00B3, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"); + public static final CipherSuite TLS_DHE_PSK_WITH_NULL_SHA256 = + new CipherSuite((short) 0x00B4, "TLS_DHE_PSK_WITH_NULL_SHA256"); + public static final CipherSuite TLS_DHE_PSK_WITH_NULL_SHA384 = + new CipherSuite((short) 0x00B5, "TLS_DHE_PSK_WITH_NULL_SHA384"); + public static final CipherSuite TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0x00B6, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = + new CipherSuite((short) 0x00B7, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"); + public static final CipherSuite TLS_RSA_PSK_WITH_NULL_SHA256 = + new CipherSuite((short) 0x00B8, "TLS_RSA_PSK_WITH_NULL_SHA256"); + public static final CipherSuite TLS_RSA_PSK_WITH_NULL_SHA384 = + new CipherSuite((short) 0x00B9, "TLS_RSA_PSK_WITH_NULL_SHA384"); + public static final CipherSuite TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0x00BA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0x00BB, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0x00BC, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0x00BD, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0x00BE, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0x00BF, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = + new CipherSuite((short) 0x00C0, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"); + public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = + new CipherSuite((short) 0x00C1, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"); + public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = + new CipherSuite((short) 0x00C2, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"); + public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = + new CipherSuite((short) 0x00C3, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"); + public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = + new CipherSuite((short) 0x00C4, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"); + public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = + new CipherSuite((short) 0x00C5, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"); + public static final CipherSuite TLS_EMPTY_RENEGOTIATION_INFO_SCSV = + new CipherSuite((short) 0x00FF, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"); + public static final CipherSuite RESERVED_GREASE_0x0A0A = + new CipherSuite((short) 0x0A0A, "Reserved (GREASE)"); + public static final CipherSuite TLS_AES_128_GCM_SHA256 = + new CipherSuite((short) 0x1301, "TLS_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_AES_256_GCM_SHA384 = + new CipherSuite((short) 0x1302, "TLS_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_CHACHA20_POLY1305_SHA256 = + new CipherSuite((short) 0x1303, "TLS_CHACHA20_POLY1305_SHA256"); + public static final CipherSuite TLS_AES_128_CCM_SHA256 = + new CipherSuite((short) 0x1304, "TLS_AES_128_CCM_SHA256"); + public static final CipherSuite RESERVED_GREASE_0x1A1A = + new CipherSuite((short) 0x1A1A, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0x2A2A = + new CipherSuite((short) 0x2A2A, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0x3A3A = + new CipherSuite((short) 0x3A3A, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0x4A4A = + new CipherSuite((short) 0x4A4A, "Reserved (GREASE)"); + public static final CipherSuite TLS_FALLBACK_SCSV = + new CipherSuite((short) 0x5600, "TLS_FALLBACK_SCSV"); + public static final CipherSuite RESERVED_GREASE_0x5A5A = + new CipherSuite((short) 0x5A5A, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0x6A6A = + new CipherSuite((short) 0x6A6A, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0x7A7A = + new CipherSuite((short) 0x7A7A, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0x8A8A = + new CipherSuite((short) 0x8A8A, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0x9A9A = + new CipherSuite((short) 0x9A9A, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0xAAAA = + new CipherSuite((short) 0xAAAA, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0xBABA = + new CipherSuite((short) 0xBABA, "Reserved (GREASE)"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_NULL_SHA = + new CipherSuite((short) 0xC001, "TLS_ECDH_ECDSA_WITH_NULL_SHA"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_RC4_128_SHA = + new CipherSuite((short) 0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0xC004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0xC005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_NULL_SHA = + new CipherSuite((short) 0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = + new CipherSuite((short) 0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_ECDH_RSA_WITH_NULL_SHA = + new CipherSuite((short) 0xC00B, "TLS_ECDH_RSA_WITH_NULL_SHA"); + public static final CipherSuite TLS_ECDH_RSA_WITH_RC4_128_SHA = + new CipherSuite((short) 0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0xC00E, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0xC00F, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_NULL_SHA = + new CipherSuite((short) 0xC010, "TLS_ECDHE_RSA_WITH_NULL_SHA"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_RC4_128_SHA = + new CipherSuite((short) 0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_ECDH_anon_WITH_NULL_SHA = + new CipherSuite((short) 0xC015, "TLS_ECDH_anon_WITH_NULL_SHA"); + public static final CipherSuite TLS_ECDH_anon_WITH_RC4_128_SHA = + new CipherSuite((short) 0xC016, "TLS_ECDH_anon_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0xC017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_ECDH_anon_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_ECDH_anon_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0xC01A, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0xC01B, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0xC01C, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_SRP_SHA_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0xC01D, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0xC01E, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0xC01F, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_SRP_SHA_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0xC020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0xC021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0xC022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = + new CipherSuite((short) 0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0xC025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = + new CipherSuite((short) 0xC026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = + new CipherSuite((short) 0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0xC029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = + new CipherSuite((short) 0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_RC4_128_SHA = + new CipherSuite((short) 0xC033, "TLS_ECDHE_PSK_WITH_RC4_128_SHA"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = + new CipherSuite((short) 0xC034, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = + new CipherSuite((short) 0xC035, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = + new CipherSuite((short) 0xC036, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = + new CipherSuite((short) 0xC037, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = + new CipherSuite((short) 0xC038, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_NULL_SHA = + new CipherSuite((short) 0xC039, "TLS_ECDHE_PSK_WITH_NULL_SHA"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_NULL_SHA256 = + new CipherSuite((short) 0xC03A, "TLS_ECDHE_PSK_WITH_NULL_SHA256"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_NULL_SHA384 = + new CipherSuite((short) 0xC03B, "TLS_ECDHE_PSK_WITH_NULL_SHA384"); + public static final CipherSuite TLS_RSA_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC03C, "TLS_RSA_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_RSA_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC03D, "TLS_RSA_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC03E, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC03F, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC040, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC041, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC042, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC043, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC044, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC045, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC046, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC047, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC048, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC049, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC04A, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC04B, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC04C, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC04D, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC04E, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC04F, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_RSA_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC050, "TLS_RSA_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_RSA_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC051, "TLS_RSA_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC052, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC053, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC054, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC055, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC056, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC057, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC058, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC059, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC05A, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC05B, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC05C, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC05D, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC05E, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC05F, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC060, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC061, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC062, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC063, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_PSK_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC064, "TLS_PSK_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_PSK_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC065, "TLS_PSK_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC066, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC067, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC068, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC069, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_PSK_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC06A, "TLS_PSK_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_PSK_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC06B, "TLS_PSK_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC06C, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC06D, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC06E, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"); + public static final CipherSuite TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC06F, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC070, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC071, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC072, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC073, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC074, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC075, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC076, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC077, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC078, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC079, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384"); + public static final CipherSuite TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC07A, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC07B, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC07C, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC07D, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC07E, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC07F, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC080, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC081, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC082, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC083, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC084, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC085, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC086, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC087, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC088, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC089, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC08A, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC08B, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC08C, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC08D, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC08E, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC08F, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC090, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC091, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = + new CipherSuite((short) 0xC092, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"); + public static final CipherSuite TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = + new CipherSuite((short) 0xC093, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"); + public static final CipherSuite TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC094, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC095, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"); + public static final CipherSuite TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC096, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC097, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"); + public static final CipherSuite TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC098, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC099, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = + new CipherSuite((short) 0xC09A, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = + new CipherSuite((short) 0xC09B, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"); + public static final CipherSuite TLS_RSA_WITH_AES_128_CCM = + new CipherSuite((short) 0xC09C, "TLS_RSA_WITH_AES_128_CCM"); + public static final CipherSuite TLS_RSA_WITH_AES_256_CCM = + new CipherSuite((short) 0xC09D, "TLS_RSA_WITH_AES_256_CCM"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CCM = + new CipherSuite((short) 0xC09E, "TLS_DHE_RSA_WITH_AES_128_CCM"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CCM = + new CipherSuite((short) 0xC09F, "TLS_DHE_RSA_WITH_AES_256_CCM"); + public static final CipherSuite TLS_RSA_WITH_AES_128_CCM_8 = + new CipherSuite((short) 0xC0A0, "TLS_RSA_WITH_AES_128_CCM_8"); + public static final CipherSuite TLS_RSA_WITH_AES_256_CCM_8 = + new CipherSuite((short) 0xC0A1, "TLS_RSA_WITH_AES_256_CCM_8"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CCM_8 = + new CipherSuite((short) 0xC0A2, "TLS_DHE_RSA_WITH_AES_128_CCM_8"); + public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CCM_8 = + new CipherSuite((short) 0xC0A3, "TLS_DHE_RSA_WITH_AES_256_CCM_8"); + public static final CipherSuite TLS_PSK_WITH_AES_128_CCM = + new CipherSuite((short) 0xC0A4, "TLS_PSK_WITH_AES_128_CCM"); + public static final CipherSuite TLS_PSK_WITH_AES_256_CCM = + new CipherSuite((short) 0xC0A5, "TLS_PSK_WITH_AES_256_CCM"); + public static final CipherSuite TLS_DHE_PSK_WITH_AES_128_CCM = + new CipherSuite((short) 0xC0A6, "TLS_DHE_PSK_WITH_AES_128_CCM"); + public static final CipherSuite TLS_DHE_PSK_WITH_AES_256_CCM = + new CipherSuite((short) 0xC0A7, "TLS_DHE_PSK_WITH_AES_256_CCM"); + public static final CipherSuite TLS_PSK_WITH_AES_128_CCM_8 = + new CipherSuite((short) 0xC0A8, "TLS_PSK_WITH_AES_128_CCM_8"); + public static final CipherSuite TLS_PSK_WITH_AES_256_CCM_8 = + new CipherSuite((short) 0xC0A9, "TLS_PSK_WITH_AES_256_CCM_8"); + public static final CipherSuite TLS_PSK_DHE_WITH_AES_128_CCM_8 = + new CipherSuite((short) 0xC0AA, "TLS_PSK_DHE_WITH_AES_128_CCM_8"); + public static final CipherSuite TLS_PSK_DHE_WITH_AES_256_CCM_8 = + new CipherSuite((short) 0xC0AB, "TLS_PSK_DHE_WITH_AES_256_CCM_8"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CCM = + new CipherSuite((short) 0xC0AC, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CCM = + new CipherSuite((short) 0xC0AD, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = + new CipherSuite((short) 0xC0AE, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = + new CipherSuite((short) 0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"); + public static final CipherSuite TLS_ECCPWD_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0xC0B0, "TLS_ECCPWD_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_ECCPWD_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0xC0B1, "TLS_ECCPWD_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_ECCPWD_WITH_AES_128_CCM_SHA256 = + new CipherSuite((short) 0xC0B2, "TLS_ECCPWD_WITH_AES_128_CCM_SHA256"); + public static final CipherSuite TLS_ECCPWD_WITH_AES_256_CCM_SHA384 = + new CipherSuite((short) 0xC0B3, "TLS_ECCPWD_WITH_AES_256_CCM_SHA384"); + public static final CipherSuite RESERVED_GREASE_0xCACA = + new CipherSuite((short) 0xCACA, "Reserved (GREASE)"); + public static final CipherSuite TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = + new CipherSuite((short) 0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"); + public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = + new CipherSuite((short) 0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"); + public static final CipherSuite TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = + new CipherSuite((short) 0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"); + public static final CipherSuite TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = + new CipherSuite((short) 0xCCAB, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = + new CipherSuite((short) 0xCCAC, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256"); + public static final CipherSuite TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = + new CipherSuite((short) 0xCCAD, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256"); + public static final CipherSuite TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = + new CipherSuite((short) 0xCCAE, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 = + new CipherSuite((short) 0xD001, "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 = + new CipherSuite((short) 0xD002, "TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256 = + new CipherSuite((short) 0xD003, "TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256"); + public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 = + new CipherSuite((short) 0xD005, "TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256"); + public static final CipherSuite RESERVED_GREASE_0xDADA = + new CipherSuite((short) 0xDADA, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0xEAEA = + new CipherSuite((short) 0xEAEA, "Reserved (GREASE)"); + public static final CipherSuite RESERVED_GREASE_0xFAFA = + new CipherSuite((short) 0xFAFA, "Reserved (GREASE)"); + + public CipherSuite(Short value, String name) { + super(value, name); + registry.put(value, this); + } + + public static CipherSuite getInstance(Short value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + throw new IllegalArgumentException("Unknown cipher suite: " + value); + } + } + + @Override + public int compareTo(CipherSuite o) { + return value().compareTo(o.value()); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CompressionMethod.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CompressionMethod.java new file mode 100644 index 000000000..731dd054d --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CompressionMethod.java @@ -0,0 +1,38 @@ +package org.pcap4j.packet.namednumber.tls; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +import java.util.Map; + +public class CompressionMethod extends NamedNumber { + + // https://www.iana.org/assignments/comp-meth-ids/comp-meth-ids.xhtml + + public static final CompressionMethod NULL = new CompressionMethod((byte) 0, "null"); + public static final CompressionMethod DEFLATE = new CompressionMethod((byte) 1, "Deflate"); + public static final CompressionMethod LZS = new CompressionMethod((byte) 64, "LZS"); + + private static final Map registry = new HashMap<>(); + + static { + registry.put(NULL.value(), NULL); + } + + public CompressionMethod(Byte value, String name) { + super(value, name); + } + + public static CompressionMethod getInstance(Byte value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + return new CompressionMethod(value, "Unknown"); + } + } + + @Override + public int compareTo(CompressionMethod o) { + return value().compareTo(o.value()); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ContentType.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ContentType.java new file mode 100644 index 000000000..cb14f9af7 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ContentType.java @@ -0,0 +1,44 @@ +package org.pcap4j.packet.namednumber.tls; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +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<>(); + + static { + registry.put(CHANGE_CIPHER_SPEC.value(), CHANGE_CIPHER_SPEC); + registry.put(ALERT.value(), ALERT); + registry.put(HANDSHAKE.value(), HANDSHAKE); + registry.put(APPLICATION_DATA.value(), APPLICATION_DATA); + registry.put(HEARTBEAT.value(), HEARTBEAT); + } + + public ContentType(Byte value, String name) { + super(value, name); + } + + public static ContentType getInstance(Byte value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + throw new IllegalArgumentException("Unknown record type " + value); + } + } + + @Override + public int compareTo(ContentType o) { + return value().compareTo(o.value()); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ExtensionType.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ExtensionType.java new file mode 100644 index 000000000..8c3504944 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ExtensionType.java @@ -0,0 +1,98 @@ +package org.pcap4j.packet.namednumber.tls; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("unused") +public class ExtensionType extends NamedNumber { + + private static final Map registry = new HashMap<>(); + + public static final ExtensionType SERVER_NAME = new ExtensionType((short) 0, "server_name"); + public static final ExtensionType MAX_FRAGMENT_LENGTH = new ExtensionType((short) 1, "max_fragment_length"); + public static final ExtensionType CLIENT_CERTIFICATE_URL = new ExtensionType((short) 2, "client_certificate_url"); + public static final ExtensionType TRUSTED_CA_KEYS = new ExtensionType((short) 3, "trusted_ca_keys"); + public static final ExtensionType TRUNCATED_HMAC = new ExtensionType((short) 4, "truncated_hmac"); + public static final ExtensionType STATUS_REQUEST = new ExtensionType((short) 5, "status_request"); + public static final ExtensionType USER_MAPPING = new ExtensionType((short) 6, "user_mapping"); + public static final ExtensionType CLIENT_AUTHZ = new ExtensionType((short) 7, "client_authz"); + public static final ExtensionType SERVER_AUTHZ = new ExtensionType((short) 8, "server_authz"); + public static final ExtensionType CERT_TYPE = new ExtensionType((short) 9, "cert_type"); + public static final ExtensionType SUPPORTED_GROUPS = new ExtensionType((short) 10, "supported_groups"); + public static final ExtensionType EC_POINT_FORMATS = new ExtensionType((short) 11, "ec_point_formats"); + public static final ExtensionType SRP = new ExtensionType((short) 12, "srp"); + public static final ExtensionType SIGNATURE_ALGORITHMS = new ExtensionType((short) 13, "signature_algorithms"); + public static final ExtensionType USE_SRTP = new ExtensionType((short) 14, "use_srtp"); + public static final ExtensionType HEARTBEAT = new ExtensionType((short) 15, "heartbeat"); + public static final ExtensionType APPLICATION_LAYER_PROTOCOL_NEGOTIATION = new ExtensionType((short) 16, "application_layer_protocol_negotiation"); + public static final ExtensionType STATUS_REQUEST_V2 = new ExtensionType((short) 17, "status_request_v2"); + public static final ExtensionType SIGNED_CERTIFICATE_TIMESTAMP = new ExtensionType((short) 18, "signed_certificate_timestamp"); + public static final ExtensionType CLIENT_CERTIFICATE_TYPE = new ExtensionType((short) 19, "client_certificate_type"); + public static final ExtensionType SERVER_CERTIFICATE_TYPE = new ExtensionType((short) 20, "server_certificate_type"); + public static final ExtensionType PADDING = new ExtensionType((short) 21, "padding"); + public static final ExtensionType ENCRYPT_THEN_MAC = new ExtensionType((short) 22, "encrypt_then_mac"); + public static final ExtensionType EXTENDED_MASTER_SECRET = new ExtensionType((short) 23, "extended_master_secret"); + public static final ExtensionType TOKEN_BINDING = new ExtensionType((short) 24, "token_binding"); + public static final ExtensionType CACHED_INFO = new ExtensionType((short) 25, "cached_info"); + public static final ExtensionType TLS_LTS = new ExtensionType((short) 26, "tls_lts"); + public static final ExtensionType COMPRESS_CERTIFICATE = new ExtensionType((short) 27, "compress_certificate"); + public static final ExtensionType RECORD_SIZE_LIMIT = new ExtensionType((short) 28, "record_size_limit"); + public static final ExtensionType PWD_PROTECT = new ExtensionType((short) 29, "pwd_protect"); + public static final ExtensionType PWD_CLEAR = new ExtensionType((short) 30, "pwd_clear"); + public static final ExtensionType PASSWORD_SALT = new ExtensionType((short) 31, "password_salt"); + public static final ExtensionType TICKET_PINNING = new ExtensionType((short) 32, "ticket_pinning"); + public static final ExtensionType TLS_CERT_WITH_EXTERN_PSK = new ExtensionType((short) 33, "tls_cert_with_extern_psk"); + public static final ExtensionType DELEGATED_CREDENTIALS = new ExtensionType((short) 34, "delegated_credentials"); + public static final ExtensionType SESSION_TICKET = new ExtensionType((short) 35, "session_ticket"); + public static final ExtensionType PRE_SHARED_KEY = new ExtensionType((short) 41, "pre_shared_key"); + public static final ExtensionType EARLY_DATA = new ExtensionType((short) 42, "early_data"); + public static final ExtensionType SUPPORTED_VERSIONS = new ExtensionType((short) 43, "supported_versions"); + public static final ExtensionType COOKIE = new ExtensionType((short) 44, "cookie"); + public static final ExtensionType PSK_KEY_EXCHANGE_MODES = new ExtensionType((short) 45, "psk_key_exchange_modes"); + public static final ExtensionType CERTIFICATE_AUTHORITIES = new ExtensionType((short) 47, "certificate_authorities"); + public static final ExtensionType OID_FILTERS = new ExtensionType((short) 48, "oid_filters"); + public static final ExtensionType POST_HANDSHAKE_AUTH = new ExtensionType((short) 49, "post_handshake_auth"); + public static final ExtensionType SIGNATURE_ALGORITHMS_CERT = new ExtensionType((short) 50, "signature_algorithms_cert"); + public static final ExtensionType KEY_SHARE = new ExtensionType((short) 51, "key_share"); + public static final ExtensionType TRANSPARENCY_INFO = new ExtensionType((short) 52, "transparency_info"); + public static final ExtensionType CONNECTION_ID = new ExtensionType((short) 53, "connection_id"); + public static final ExtensionType EXTERNAL_ID_HASH = new ExtensionType((short) 55, "external_id_hash"); + public static final ExtensionType EXTERNAL_SESSION_ID = new ExtensionType((short) 56, "external_session_id"); + public static final ExtensionType RESERVED_GREASE_2570 = new ExtensionType((short) 2570, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_6682 = new ExtensionType((short) 6682, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_10794 = new ExtensionType((short) 10794, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_14906 = new ExtensionType((short) 14906, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_19018 = new ExtensionType((short) 19018, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_23130 = new ExtensionType((short) 23130, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_27242 = new ExtensionType((short) 27242, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_31354 = new ExtensionType((short) 31354, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_35466 = new ExtensionType((short) 35466, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_39578 = new ExtensionType((short) 39578, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_43690 = new ExtensionType((short) 43690, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_47802 = new ExtensionType((short) 47802, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_51914 = new ExtensionType((short) 51914, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_56026 = new ExtensionType((short) 56026, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_60138 = new ExtensionType((short) 60138, "Reserved (GREASE)"); + public static final ExtensionType RESERVED_GREASE_64250 = new ExtensionType((short) 64250, "Reserved (GREASE)"); + public static final ExtensionType RENEGOTIATION_INFO = new ExtensionType((short) 65281, "renegotiation_info"); + + public ExtensionType(Short value, String name) { + super(value, name); + registry.put(value, this); + } + + public static ExtensionType getInstance(Short value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + return new ExtensionType(value, "Unknown"); + } + } + + @Override + public int compareTo(ExtensionType o) { + return value().compareTo(o.value()); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HandshakeType.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HandshakeType.java new file mode 100644 index 000000000..690733414 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HandshakeType.java @@ -0,0 +1,52 @@ +package org.pcap4j.packet.namednumber.tls; + +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<>(); + + // 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"); + public static final HandshakeType SERVER_HELLO_DONE = new HandshakeType((byte) 14, "Server Hello Done"); + 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"); + 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 static final HandshakeType ENCRYPTED_HANDSHAKE_MESSAGE = new HandshakeType((byte) 255, "Encrypted Handshake Message"); + + public HandshakeType(Byte value, String name) { + super(value, name); + registry.put(value, this); + } + + public static HandshakeType getInstance(Byte value) { + return registry.getOrDefault(value, ENCRYPTED_HANDSHAKE_MESSAGE); + } + + @Override + public int compareTo(HandshakeType o) { + return value().compareTo(o.value()); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HeartbeatMessageType.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HeartbeatMessageType.java new file mode 100644 index 000000000..3b7fd4fb9 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HeartbeatMessageType.java @@ -0,0 +1,33 @@ +package org.pcap4j.packet.namednumber.tls; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +import java.util.Map; + +public class HeartbeatMessageType extends NamedNumber { + + private static final Map registry = new HashMap<>(); + + public static final HeartbeatMessageType HEARTBEAT_REQUEST = new HeartbeatMessageType((byte) 1, "heartbeat_request"); + public static final HeartbeatMessageType HEARTBEAT_RESPONSE = new HeartbeatMessageType((byte) 2, "heartbeat_response"); + + public HeartbeatMessageType(Byte value, String name) { + super(value, name); + registry.put(value, this); + } + + public static HeartbeatMessageType getInstance(Byte value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + throw new IllegalArgumentException("Unknown heartbeat message type: " + value); + } + } + + @Override + public int compareTo(HeartbeatMessageType o) { + return value().compareTo(o.value()); + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/KeyGroup.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/KeyGroup.java new file mode 100644 index 000000000..a097fe481 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/KeyGroup.java @@ -0,0 +1,98 @@ +package org.pcap4j.packet.namednumber.tls; + +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/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/TlsVersion.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/TlsVersion.java new file mode 100644 index 000000000..cb0cf2bdb --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/TlsVersion.java @@ -0,0 +1,41 @@ +package org.pcap4j.packet.namednumber.tls; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +import java.util.Map; + +public class TlsVersion extends NamedNumber { + + public static final TlsVersion TLS_1_0 = new TlsVersion((short) 0x0301, "TLS 1.0"); + public static final TlsVersion TLS_1_1 = new TlsVersion((short) 0x0302, "TLS 1.1"); + public static final TlsVersion TLS_1_2 = new TlsVersion((short) 0x0303, "TLS 1.2"); + public static final TlsVersion TLS_1_3 = new TlsVersion((short) 0x0304, "TLS 1.3"); + + private static final Map registry = new HashMap<>(); + + static { + registry.put(TLS_1_0.value(), TLS_1_0); + registry.put(TLS_1_1.value(), TLS_1_1); + registry.put(TLS_1_2.value(), TLS_1_2); + registry.put(TLS_1_3.value(), TLS_1_3); + } + + public TlsVersion(Short value, String name) { + super(value, name); + } + + public static TlsVersion getInstance(Short value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + return new TlsVersion(value, "unknown"); + } + } + + @Override + public int compareTo(TlsVersion o) { + return value().compareTo(o.value()); + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java new file mode 100644 index 000000000..b016c8866 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java @@ -0,0 +1,49 @@ +package org.pcap4j.packet.tls.extensions; + +import org.pcap4j.packet.namednumber.tls.ExtensionType; +import org.pcap4j.packet.tls.extensions.keyshare.KeyShareExtension; +import org.pcap4j.util.ByteArrays; + +public abstract class TlsExtension { + + /* + 0x0 - Type + 0x2 - Length + 0x4 - Content + 0x4+length - End + */ + + protected ExtensionType type; + protected short extensionLength; + + public static TlsExtension newInstance(ExtensionType type, byte[] rawData, int offset, + short extensionLength, boolean client) { + if (extensionLength > 0) { + ByteArrays.validateBounds(rawData, offset, extensionLength); + } + + if (type == ExtensionType.KEY_SHARE) { + return KeyShareExtension.newInstance(type, rawData, offset, extensionLength, client); + } else { + return new UnimplementedTlsExtension(type, rawData, offset, extensionLength); + } + } + + public TlsExtension(ExtensionType type, short extensionLength) { + this.type = type; + this.extensionLength = extensionLength; + } + + public ExtensionType getType() { + return type; + } + + public short getLength() { + return extensionLength; + } + + @Override + public String toString() { + return type.name(); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java new file mode 100644 index 000000000..cc6d8e7cc --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java @@ -0,0 +1,24 @@ +package org.pcap4j.packet.tls.extensions; + +import org.pcap4j.packet.namednumber.tls.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() { + if(extensionLength > 0) { + return type.name() + " [" + extensionLength + " bytes]"; + } else { + return type.name(); + } + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java new file mode 100644 index 000000000..dae9a9c6a --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java @@ -0,0 +1,23 @@ +package org.pcap4j.packet.tls.extensions.keyshare; + +import org.pcap4j.util.ByteArrays; +import org.pcap4j.packet.namednumber.tls.ExtensionType; + +import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; + +public class ClientKeyShareExtension extends KeyShareExtension { + + 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; + + public ClientKeyShareExtension(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 + int cursor = KEY_SHARE_ENTRY_OFFSET + offset; + ByteArrays.validateBounds(rawData, cursor, keyShareLength); + readEntries(rawData, KEY_SHARE_ENTRY_OFFSET + offset, offset + keyShareLength); + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java new file mode 100644 index 000000000..ee4e348e9 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java @@ -0,0 +1,33 @@ +package org.pcap4j.packet.tls.extensions.keyshare; + +import org.pcap4j.util.ByteArrays; +import org.pcap4j.packet.namednumber.tls.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/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java new file mode 100644 index 000000000..16829f863 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java @@ -0,0 +1,46 @@ +package org.pcap4j.packet.tls.extensions.keyshare; + +import org.pcap4j.packet.tls.extensions.TlsExtension; +import org.pcap4j.util.ByteArrays; +import org.pcap4j.packet.namednumber.tls.ExtensionType; + +import java.util.ArrayList; +import java.util.List; + +public abstract class KeyShareExtension extends TlsExtension { + + private final List entries = new ArrayList<>(); + + public static KeyShareExtension newInstance(ExtensionType type, byte[] rawData, int offset, + short extensionLength, boolean client) { + ByteArrays.validateBounds(rawData, offset, extensionLength); + + if(client) { + return new ClientKeyShareExtension(type, rawData, offset, extensionLength); + } else { + return new ServerKeyShareExtension(type, rawData, offset, extensionLength); + } + } + + protected KeyShareExtension(ExtensionType type, short extensionLength) { + super(type, extensionLength); + } + + protected void readEntries(byte[] rawData, int cursor, int end) { + while (cursor < end) { + KeyShareEntry entry = readEntry(rawData, cursor); + cursor += entry.size(); + } + } + + protected KeyShareEntry readEntry(byte[] rawData, int cursor) { + KeyShareEntry entry = new KeyShareEntry(rawData, cursor); + entries.add(entry); + return entry; + } + + @Override + public String toString() { + return type.name() + " " + entries.toString(); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java new file mode 100644 index 000000000..a7aea49f5 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java @@ -0,0 +1,14 @@ +package org.pcap4j.packet.tls.extensions.keyshare; + +import org.pcap4j.packet.namednumber.tls.ExtensionType; + +public class ServerKeyShareExtension extends KeyShareExtension { + + private static final int KEY_SHARE_ENTRY_OFFSET = 0; + + public ServerKeyShareExtension(ExtensionType type, byte[] rawData, int offset, short extensionLength) { + super(type, extensionLength); + readEntry(rawData, KEY_SHARE_ENTRY_OFFSET + offset); + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/DhClientParams.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/DhClientParams.java new file mode 100644 index 000000000..a8fc3321d --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/DhClientParams.java @@ -0,0 +1,42 @@ +package org.pcap4j.packet.tls.keys; + +import org.pcap4j.packet.tls.keys.enums.SignatureScheme; + +public class DhClientParams { + + private final byte[] p; + private final byte[] g; + private final byte[] pubkey; + private final SignatureScheme signatureScheme; + private final byte[] signature; + + public DhClientParams(byte[] p, byte[] g, byte[] pubkey, + SignatureScheme signatureScheme, + byte[] signature) { + this.p = p; + this.g = g; + this.pubkey = pubkey; + this.signatureScheme = signatureScheme; + this.signature = signature; + } + + public byte[] getP() { + return p; + } + + public byte[] getG() { + return g; + } + + public byte[] getPubkey() { + return pubkey; + } + + public SignatureScheme getSignatureScheme() { + return signatureScheme; + } + + public byte[] getSignature() { + return signature; + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/EcdheServerParams.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/EcdheServerParams.java new file mode 100644 index 000000000..9b7fa9042 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/EcdheServerParams.java @@ -0,0 +1,44 @@ +package org.pcap4j.packet.tls.keys; + +import org.pcap4j.packet.tls.keys.enums.CurveType; +import org.pcap4j.packet.tls.keys.enums.NamedCurve; +import org.pcap4j.packet.tls.keys.enums.SignatureScheme; + +public class EcdheServerParams { + + private final CurveType curveType; + private final NamedCurve namedCurve; + private final byte[] pubkey; + private final SignatureScheme signatureScheme; + private final byte[] signature; + + public EcdheServerParams(CurveType curveType, NamedCurve namedCurve, byte[] pubkey, + SignatureScheme signatureScheme, + byte[] signature) { + this.curveType = curveType; + this.namedCurve = namedCurve; + this.pubkey = pubkey; + this.signatureScheme = signatureScheme; + this.signature = signature; + } + + public CurveType getCurveType() { + return curveType; + } + + public NamedCurve getNamedCurve() { + return namedCurve; + } + + public byte[] getPubkey() { + return pubkey; + } + + public SignatureScheme getSignatureScheme() { + return signatureScheme; + } + + public byte[] getSignature() { + return signature; + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/TlsKeyUtils.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/TlsKeyUtils.java new file mode 100644 index 000000000..07f551632 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/TlsKeyUtils.java @@ -0,0 +1,108 @@ +package org.pcap4j.packet.tls.keys; + +import org.pcap4j.packet.tls.keys.enums.CurveType; +import org.pcap4j.packet.tls.keys.enums.NamedCurve; +import org.pcap4j.packet.tls.keys.enums.SignatureScheme; + +import java.nio.ByteBuffer; + +/** + * It is impossible to determine key format just by KeyExchange record, + * so you can use this class when analyzing tls traffic. + */ +public final class TlsKeyUtils { + + // https://wiki.osdev.org/TLS_Handshake + + public static DhClientParams parseServerDH(byte[] rawData, int offset) { + ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset); + + short pLength = bb.getShort(); + byte[] p = new byte[pLength]; + bb.get(p); + + short gLength = bb.getShort(); + byte[] g = new byte[gLength]; + bb.get(g); + + short pubKeyLength = bb.getShort(); + byte[] pubKey = new byte[pubKeyLength]; // aka Ys + bb.get(pubKey); + + SignatureScheme signatureScheme = SignatureScheme.findByValue(bb.getShort()); + + if (signatureScheme == null) { + throw new IllegalArgumentException("Unknown signature scheme"); + } + + short signatureLength = bb.getShort(); + byte[] signature = new byte[signatureLength]; + + bb.get(signature); + + return new DhClientParams(p, g, pubKey, signatureScheme, signature); + } + + /** + * @param rawData Handshake record content + */ + public static EcdheServerParams parseServerECDHE(byte[] rawData, int offset) { + ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset); + + byte curveTypeId = bb.get(); + if(curveTypeId != 0x03) { + throw new IllegalArgumentException("Unsupported curve type"); + } + + CurveType curveType = CurveType.NAMED; + NamedCurve namedCurve = NamedCurve.findByValue(bb.getShort()); + + if (namedCurve == null) { + throw new IllegalArgumentException("Unsupported named curve"); + } + + byte pubkeyLength = bb.get(); + byte[] pubkey = new byte[pubkeyLength]; + bb.get(pubkey); + + SignatureScheme signatureScheme = SignatureScheme.findByValue(bb.getShort()); + + if (signatureScheme == null) { + throw new IllegalArgumentException("Unknown signature scheme"); + } + + short signatureLength = bb.getShort(); + byte[] signature = new byte[signatureLength]; + + bb.get(signature); + + return new EcdheServerParams(curveType, namedCurve, pubkey, signatureScheme, signature); + } + + // https://ldapwiki.com/wiki/ClientKeyExchange + + /** + * Suitable for both DH and ECDHE + * @param rawData Handshake record content + */ + public static byte[] getClientDHPubkey(byte[] rawData, int offset) { + ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset); + + byte length = bb.get(); + byte[] pubkey = new byte[length]; + bb.get(pubkey); + + return pubkey; + } + + public static byte[] getClientRsaPreMaster(byte[] rawData, int offset) { + ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset); + + int length = bb.getShort(); + byte[] encryptedPreMaster = new byte[length]; + bb.get(encryptedPreMaster); + + return encryptedPreMaster; + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/CurveType.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/CurveType.java new file mode 100644 index 000000000..63c5bb660 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/CurveType.java @@ -0,0 +1,16 @@ +package org.pcap4j.packet.tls.keys.enums; + +public enum CurveType { + + NAMED((byte) 0x03); + + private final byte value; + + CurveType(byte value) { + this.value = value; + } + + public byte getValue() { + return value; + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/NamedCurve.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/NamedCurve.java new file mode 100644 index 000000000..00f248773 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/NamedCurve.java @@ -0,0 +1,57 @@ +package org.pcap4j.packet.tls.keys.enums; + +import java.util.HashMap; +import java.util.Map; + +public enum NamedCurve { + + SECT163K1((short) 1), + SECT163R1((short) 2), + SECT163R2((short) 3), + SECT193R1((short) 4), + SECT193R2((short) 5), + SECT233K1((short) 6), + SECT233R1((short) 7), + SECT239K1((short) 8), + SECT283K1((short) 9), + SECT283R1((short) 10), + SECT409K1((short) 11), + SECT409R1((short) 12), + SECT571K1((short) 13), + SECT571R1((short) 14), + SECP160K1((short) 15), + SECP160R1((short) 16), + SECP160R2((short) 17), + SECP192K1((short) 18), + SECP192R1((short) 19), + SECP224K1((short) 20), + SECP224R1((short) 21), + SECP256K1((short) 22), + SECP256R1((short) 23), + SECP384R1((short) 24), + SECP521R1((short) 25), + X25519((short) 29), + X448((short) 30); + + private final short value; + + private static final Map map = new HashMap<>(); + + NamedCurve(short value) { + this.value = value; + } + + static { + for (NamedCurve curve : values()) { + map.put(curve.getValue(), curve); + } + } + + public short getValue() { + return value; + } + + public static NamedCurve findByValue(short value) { + return map.get(value); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/SignatureScheme.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/SignatureScheme.java new file mode 100644 index 000000000..452c6f1fc --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/SignatureScheme.java @@ -0,0 +1,58 @@ +package org.pcap4j.packet.tls.keys.enums; + +import java.util.HashMap; +import java.util.Map; + +public enum SignatureScheme { + + /* RSASSA-PKCS1-v1_5 algorithms */ + RSA_PKCS1_SHA256((short) 0x0401), + RSA_PKCS1_SHA384((short) 0x0501), + RSA_PKCS1_SHA512((short) 0x0601), + + /* ECDSA algorithms */ + ECDSA_SECP256R1_SHA256((short) 0x0403), + ECDSA_SECP384R1_SHA384((short) 0x0503), + ECDSA_SECP521R1_SHA512((short) 0x0603), + + /* RSASSA-PSS algorithms with public key OID RSAEncryption */ + RSA_PSS_RSAE_SHA256((short) 0x0804), + RSA_PSS_RSAE_SHA384((short) 0x0805), + RSA_PSS_RSAE_SHA512((short) 0x0806), + + /* EDDSA algorithms */ + ED25519((short) 0x0807), + ED448((short) 0x0808), + + /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */ + RSA_PSS_PSS_SHA256((short) 0x0809), + RSA_PSS_PSS_SHA384((short) 0x080a), + RSA_PSS_PSS_SHA512((short) 0x080b), + + /* Legacy algorithms */ + RSA_PKCS1_SHA1((short) 0x0201), + ECDSA_SHA1((short) 0x0203); + + private final short value; + + private static final Map map = new HashMap<>(); + + SignatureScheme(short value) { + this.value = value; + } + + static { + for (SignatureScheme curve : values()) { + map.put(curve.getValue(), curve); + } + } + + public short getValue() { + return value; + } + + public static SignatureScheme findByValue(short value) { + return map.get(value); + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java new file mode 100644 index 000000000..113591c8b --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java @@ -0,0 +1,37 @@ +package org.pcap4j.packet.tls.records; + +import org.pcap4j.util.ByteArrays; +import org.pcap4j.packet.namednumber.tls.AlertDescription; +import org.pcap4j.packet.namednumber.tls.AlertLevel; + +import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; + +public class AlertRecord implements TlsRecord { + + /** + * 0x0 - Alert level + * 0x1 - Alert description + * 0x2 - End + */ + + private static final int LEVEL_OFFSET = 0; + private static final int DESCRIPTION_OFFSET = LEVEL_OFFSET + BYTE_SIZE_IN_BYTES; + + private AlertLevel level; + private AlertDescription description; + + public static AlertRecord newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); + return new AlertRecord(rawData, offset); + } + + public AlertRecord(byte[] rawData, int offset) { + this.level = AlertLevel.getInstance(ByteArrays.getByte(rawData, LEVEL_OFFSET + offset)); + this.description = AlertDescription.getInstance(ByteArrays.getByte(rawData, DESCRIPTION_OFFSET + offset)); + } + + @Override + public String toString() { + return " Alert [level: " + level.name() + ", description: " + description.name() + "]"; + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java new file mode 100644 index 000000000..3cd16af52 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java @@ -0,0 +1,33 @@ +package org.pcap4j.packet.tls.records; + +import org.pcap4j.util.ByteArrays; + +public class ApplicationDataRecord implements TlsRecord { + + /** + * 0x0 - Encrypted Application Data + * 0x0 + length - End + */ + + private byte[] data; + + public static ApplicationDataRecord newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); + return new ApplicationDataRecord(rawData, offset, length); + } + + public ApplicationDataRecord(byte[] rawData, int offset, int length) { + data = new byte[length]; + System.arraycopy(rawData, offset, data, 0, length); + } + + public byte[] getData() { + return data; + } + + @Override + public String toString() { + return " Encrypted data: [" + data.length + " bytes]"; + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java new file mode 100644 index 000000000..1e9269848 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java @@ -0,0 +1,27 @@ +package org.pcap4j.packet.tls.records; + +import org.pcap4j.util.ByteArrays; + +public class ChangeCipherSpecRecord implements TlsRecord { + + /** + 0x0 - Change Cipher Spec Message + 0x1 - End + */ + + private byte changeCipherSpecMessage; + + public static ChangeCipherSpecRecord newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); + return new ChangeCipherSpecRecord(rawData, offset); + } + + private ChangeCipherSpecRecord(byte[] rawData, int offset) { + this.changeCipherSpecMessage = ByteArrays.getByte(rawData, offset); + } + + @Override + public String toString() { + return " Change Cipher Spec Message: " + changeCipherSpecMessage; + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java new file mode 100644 index 000000000..6a77f8f99 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java @@ -0,0 +1,72 @@ +package org.pcap4j.packet.tls.records; + +import org.pcap4j.packet.tls.records.handshakes.*; +import org.pcap4j.util.ByteArrays; +import org.pcap4j.packet.namednumber.tls.HandshakeType; + +import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; + +public class HandshakeRecord implements TlsRecord { + + /* + 0x0 - Handshake type + 0x1 - Handshake length + 0x4 - Handshake version + 0x6 - Handshake content + */ + + private static final int HANDSHAKE_TYPE_OFFSET = 0; + 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) { + ByteArrays.validateBounds(rawData, offset, length); + return new HandshakeRecord(rawData, offset, length); + } + + private HandshakeRecord(byte[] rawData, int offset, int length) { + this.handshakeType = HandshakeType.getInstance(ByteArrays.getByte(rawData, HANDSHAKE_TYPE_OFFSET + offset)); + + if (handshakeType == HandshakeType.ENCRYPTED_HANDSHAKE_MESSAGE) { + this.handshakeLength = length; + this.content = BasicHandshakeRecordContent.newInstance( + rawData, offset, handshakeLength); + return; + } + + this.handshakeLength = ByteArrays.getThreeBytesInt(rawData, LENGTH_OFFSET + offset); + + if (handshakeType == HandshakeType.CLIENT_HELLO) { + this.content = ClientHelloHandshakeRecordContent.newInstance( + rawData, offset + CONTENT_OFFSET, handshakeLength); + } else if (handshakeType == HandshakeType.SERVER_HELLO) { + this.content = ServerHelloHandshakeRecordContent.newInstance( + rawData, offset + CONTENT_OFFSET, handshakeLength); + } else if (handshakeType == HandshakeType.CERTIFICATE) { + this.content = CertificateHandshakeRecordContent.newInstance( + rawData, offset + CONTENT_OFFSET, handshakeLength); + } else { + this.content = BasicHandshakeRecordContent.newInstance( + rawData, offset + CONTENT_OFFSET, handshakeLength); + } + } + + public HandshakeType getHandshakeType() { + return handshakeType; + } + + public HandshakeRecordContent getContent() { + return content; + } + + @Override + public String toString() { + return " Handshake length: " + handshakeLength + "\n" + + " Handshake type: " + handshakeType + "\n" + + content.toString(); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java new file mode 100644 index 000000000..75ebd1e3c --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java @@ -0,0 +1,53 @@ +package org.pcap4j.packet.tls.records; + +import org.pcap4j.util.ByteArrays; +import org.pcap4j.packet.namednumber.tls.HeartbeatMessageType; + +import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; +import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; + +public class HeartbeatRecord implements TlsRecord { + + //https://tools.ietf.org/html/rfc6520 + + private static final int TYPE_OFFSET = 0; + private static final int PAYLOAD_LENGTH_OFFSET = TYPE_OFFSET + BYTE_SIZE_IN_BYTES; + private static final int PAYLOAD_OFFSET = PAYLOAD_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; + + private HeartbeatMessageType type; + private short payloadLength; + private byte[] payload; + private byte[] padding; + + public static HeartbeatRecord newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); + return new HeartbeatRecord(rawData, offset, length); + } + + public HeartbeatRecord(byte[] rawData, int offset, int length) { + this.type = HeartbeatMessageType.getInstance(ByteArrays.getByte(rawData, TYPE_OFFSET + offset)); + this.payloadLength = ByteArrays.getShort(rawData, PAYLOAD_LENGTH_OFFSET + offset); + this.payload = ByteArrays.getSubArray(rawData, PAYLOAD_OFFSET + offset, payloadLength); + this.padding = ByteArrays.getSubArray(rawData, PAYLOAD_OFFSET + payloadLength + offset); + } + + public HeartbeatMessageType getType() { + return type; + } + + public byte[] getPayload() { + return payload; + } + + public byte[] getPadding() { + return padding; + } + + @Override + public String toString() { + return " Heartbeat (" + type.name() + + ") [" + payloadLength + " bytes payload, " + + padding.length + " bytes padding]"; + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/TlsRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/TlsRecord.java new file mode 100644 index 000000000..acbeb3bbd --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/TlsRecord.java @@ -0,0 +1,7 @@ +package org.pcap4j.packet.tls.records; + +import java.io.Serializable; + +public interface TlsRecord extends Serializable { + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java new file mode 100644 index 000000000..9ee09016b --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java @@ -0,0 +1,36 @@ +package org.pcap4j.packet.tls.records.handshakes; + +import org.pcap4j.util.ByteArrays; + +public class BasicHandshakeRecordContent implements HandshakeRecordContent { + + /** + * 0x0 - Content + * 0x0 + length - End + */ + + private byte[] content; + + public static BasicHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { + if(length > 0) { + ByteArrays.validateBounds(rawData, offset, length); + } + return new BasicHandshakeRecordContent(rawData, offset, length); + } + + public BasicHandshakeRecordContent(byte[] rawData, int offset, int length) { + content = new byte[length]; + if (length > 0) { + System.arraycopy(rawData, offset, content, 0, length); + } + } + + public byte[] getContent() { + return content; + } + + @Override + public String toString() { + return " [" + content.length + " bytes]"; + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java new file mode 100644 index 000000000..c71618676 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java @@ -0,0 +1,51 @@ +package org.pcap4j.packet.tls.records.handshakes; + +import org.pcap4j.util.ByteArrays; + +import java.util.ArrayList; +import java.util.List; + +public class CertificateHandshakeRecordContent implements HandshakeRecordContent { + + private static final int CERTIFICATES_LENGTH_OFFSET = 0; + private static final int CERTIFICATES_OFFSET = 3; + + private int certificatesLength; + private List rawCertificates = new ArrayList<>(); + + public static CertificateHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { + return new CertificateHandshakeRecordContent(rawData, offset, length); + } + + public CertificateHandshakeRecordContent(byte[] rawData, int offset, int length) { + this.certificatesLength = ByteArrays.getThreeBytesInt(rawData, CERTIFICATES_LENGTH_OFFSET + offset); + + int cursor = CERTIFICATES_OFFSET + offset; + while (cursor < offset + length) { + int certificateLength = ByteArrays.getThreeBytesInt(rawData, cursor); + cursor += 3; + + ByteArrays.validateBounds(rawData, cursor, certificateLength); + byte[] certData = ByteArrays.getSubArray(rawData, cursor, certificateLength); + rawCertificates.add(certData); + cursor += certificateLength; + } + } + + public List getRawCertificates() { + return rawCertificates; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(" Chain length: " + rawCertificates.size()); + + for (byte[] cert : rawCertificates) { + sb.append('\n'); + sb.append(" [").append(cert.length).append(" bytes]"); + } + + return sb.toString(); + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java new file mode 100644 index 000000000..8fd66e60f --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java @@ -0,0 +1,82 @@ +package org.pcap4j.packet.tls.records.handshakes; + +import org.pcap4j.util.ByteArrays; +import org.pcap4j.packet.namednumber.tls.CipherSuite; +import org.pcap4j.packet.namednumber.tls.CompressionMethod; + +import java.util.ArrayList; +import java.util.List; + +import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; +import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; + +public class ClientHelloHandshakeRecordContent extends HelloHandshakeRecordContent { + + /* + 0x0 - Client random + 0x20 - Session id length (sidl) + 0x21 - Session id + 0x21+sidl - Cipher suites length (csl) + 0x23+sidl - Cipher suite 1..(csl/2) + 0x23+sidl+csl - Compression methods length (cml) + 0x24+sidl+csl - Compression method 1..cml + 0x24+sidl+csl+cml - Extensions Length (el) + 0x26+sidl+csl+cml - Extension 1..N + 0x26+sidl+csl+cml+el - End + */ + + private static final int CIPHER_SUITES_LENGTH_OFFSET = HelloHandshakeRecordContent.SESSION_ID_OFFSET; // + sessionIdLength + private static final int CIPHER_SUITE_OFFSET = + CIPHER_SUITES_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; // + sessionIdLength + SHORT_SIZE_IN_BYTES*i + private static final int COMPRESSION_METHODS_LENGTH_OFFSET = CIPHER_SUITE_OFFSET; // + sessionIdLength + cipherSuitesLength + private static final int COMPRESSION_METHOD_OFFSET = + COMPRESSION_METHODS_LENGTH_OFFSET + BYTE_SIZE_IN_BYTES; // + sessionIdLength + cipherSuitesLength + BYTE_SIZE_IN_BYTES*i + private static final int EXTENSIONS_LENGTH_OFFSET = + COMPRESSION_METHOD_OFFSET; // + sessionIdLength + cipherSuitesLength + compressionMethodsLength + private static final int EXTENSIONS_OFFSET = COMPRESSION_METHOD_OFFSET + SHORT_SIZE_IN_BYTES; + + private short cipherSuitesLength; + private List cipherSuites; + private byte compressionMethodsLength; + private List compressionMethods; + + public static ClientHelloHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); + return new ClientHelloHandshakeRecordContent(rawData, offset); + } + + private ClientHelloHandshakeRecordContent(byte[] rawData, int offset) { + readCommonPart(rawData, offset); + + this.cipherSuitesLength = ByteArrays.getShort(rawData, CIPHER_SUITES_LENGTH_OFFSET + sessionIdLength + offset); + int cipherSuitesAmount = cipherSuitesLength / SHORT_SIZE_IN_BYTES; + this.cipherSuites = new ArrayList<>(cipherSuitesAmount); + + for (int i = 0; i < cipherSuitesAmount; i++) { + this.cipherSuites.add(CipherSuite.getInstance(ByteArrays.getShort(rawData, + CIPHER_SUITE_OFFSET + SHORT_SIZE_IN_BYTES * i + sessionIdLength + offset))); + } + + this.compressionMethodsLength = ByteArrays.getByte(rawData, + COMPRESSION_METHODS_LENGTH_OFFSET + cipherSuitesLength + sessionIdLength + offset); + this.compressionMethods = new ArrayList<>(compressionMethodsLength); + + for (byte i = 0; i < compressionMethodsLength; i++) { + this.compressionMethods.add(CompressionMethod.getInstance(ByteArrays.getByte(rawData, + COMPRESSION_METHOD_OFFSET + BYTE_SIZE_IN_BYTES * i + sessionIdLength + cipherSuitesLength + offset))); + } + + this.extensionsLength = ByteArrays.getShort(rawData, + EXTENSIONS_LENGTH_OFFSET + compressionMethodsLength + sessionIdLength + cipherSuitesLength + offset); + + readExtensions(rawData, EXTENSIONS_OFFSET + compressionMethodsLength + + sessionIdLength + cipherSuitesLength + offset, true); + } + + @Override + public String toString() { + return super.toString() + "\n" + + " Cipher suites: " + cipherSuites.toString() + "\n" + + " Compression methods: " + compressionMethods.toString(); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java new file mode 100644 index 000000000..c22d6456b --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java @@ -0,0 +1,4 @@ +package org.pcap4j.packet.tls.records.handshakes; + +public interface HandshakeRecordContent { +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java new file mode 100644 index 000000000..dc129dba6 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java @@ -0,0 +1,81 @@ +package org.pcap4j.packet.tls.records.handshakes; + +import org.pcap4j.packet.tls.extensions.TlsExtension; +import org.pcap4j.util.ByteArrays; +import org.pcap4j.packet.namednumber.tls.ExtensionType; +import org.pcap4j.packet.namednumber.tls.TlsVersion; + +import java.util.ArrayList; +import java.util.List; + +import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; +import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; + +public abstract class HelloHandshakeRecordContent implements HandshakeRecordContent { + + 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 TlsVersion version; + protected byte[] random = new byte[32]; + protected byte sessionIdLength; + protected byte[] sessionId; + + protected short extensionsLength; + private List extensions; + + protected void readCommonPart(byte[] rawData, int 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); + this.sessionId = new byte[sessionIdLength]; + + if (sessionIdLength != 0) { + System.arraycopy(rawData, SESSION_ID_OFFSET + offset, sessionId, 0, sessionIdLength); + } + } + + protected void readExtensions(byte[] rawData, int offset, boolean client) { + extensions = new ArrayList<>(extensionsLength); + + int cursor = offset; + int extensionsEnd = cursor + extensionsLength; + + while (cursor < extensionsEnd) { + ExtensionType extensionType = ExtensionType.getInstance(ByteArrays.getShort(rawData, cursor)); + cursor += SHORT_SIZE_IN_BYTES; + short extensionLength = ByteArrays.getShort(rawData, cursor); + cursor += SHORT_SIZE_IN_BYTES; + + extensions.add(TlsExtension.newInstance(extensionType, rawData, cursor, extensionLength, client)); + + cursor += extensionLength; + } + } + + public TlsVersion getVersion() { + return version; + } + + public byte[] getRandom() { + return random; + } + + public byte[] getSessionId() { + return sessionId; + } + + public List getExtensions() { + return extensions; + } + + @Override + public String toString() { + return " TLS version: " + version + "\n" + + " Random: " + ByteArrays.toHexString(random, "") + "\n" + + " Session id: " + (sessionIdLength > 0 ? ByteArrays.toHexString(sessionId, "") : "null") + "\n" + + " Extensions: " + extensions.toString(); + } +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java new file mode 100644 index 000000000..0d2d0964f --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java @@ -0,0 +1,64 @@ +package org.pcap4j.packet.tls.records.handshakes; + +import org.pcap4j.util.ByteArrays; +import org.pcap4j.packet.namednumber.tls.CipherSuite; +import org.pcap4j.packet.namednumber.tls.CompressionMethod; + +import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; +import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; + +public class ServerHelloHandshakeRecordContent extends HelloHandshakeRecordContent { + + /* + 0x0 - Server random + 0x20 - Session id length (sidl) + 0x21 - Session id + 0x21+si - Cipher suite + 0x23+sidl - Compression method + 0x24+sidl - Extensions Length (el) + 0x26+sidl - Extension 1..N + 0x26+sidl+el - End + */ + + private static final int CIPHER_SUITE_OFFSET = HelloHandshakeRecordContent.SESSION_ID_OFFSET; // + sessionIdLength + private static final int COMPRESSION_METHOD_OFFSET = CIPHER_SUITE_OFFSET + SHORT_SIZE_IN_BYTES; // + sessionIdLength + private static final int EXTENSIONS_LENGTH_OFFSET = COMPRESSION_METHOD_OFFSET + BYTE_SIZE_IN_BYTES; // + sessionIdLength + private static final int EXTENSIONS_OFFSET = EXTENSIONS_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; // + sessionIdLength + + private CipherSuite cipherSuite; + private CompressionMethod compressionMethod; + + public static ServerHelloHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); + return new ServerHelloHandshakeRecordContent(rawData, offset); + } + + public ServerHelloHandshakeRecordContent(byte[] rawData, int offset) { + readCommonPart(rawData, offset); + + this.cipherSuite = CipherSuite.getInstance(ByteArrays.getShort(rawData, + CIPHER_SUITE_OFFSET + sessionIdLength + offset)); + this.compressionMethod = CompressionMethod.getInstance(ByteArrays.getByte(rawData, + COMPRESSION_METHOD_OFFSET + sessionIdLength + offset)); + + this.extensionsLength = ByteArrays.getShort(rawData, + EXTENSIONS_LENGTH_OFFSET + sessionIdLength + offset); + readExtensions(rawData, EXTENSIONS_OFFSET + sessionIdLength + offset, false); + } + + public CipherSuite getCipherSuite() { + return cipherSuite; + } + + public CompressionMethod getCompressionMethod() { + return compressionMethod; + } + + @Override + public String toString() { + return super.toString() + "\n" + + " Cipher suite: " + cipherSuite.toString() + "\n" + + " Compression method: " + compressionMethod.toString(); + } + +} diff --git a/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java b/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java index 793d2db91..a03c1b5da 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java +++ b/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java @@ -314,6 +314,39 @@ public static int getInt(byte[] array, int offset, int length, ByteOrder bo) { return value; } + /** + * @param array array + * @param offset offset + * @return int value. + */ + public static int getThreeBytesInt(byte[] array, int offset) { + return getThreeBytesInt(array, offset, ByteOrder.BIG_ENDIAN); + } + + /** + * @param array array + * @param offset offset + * @param bo bo + * @return int value. + */ + public static int getThreeBytesInt(byte[] array, int offset, ByteOrder bo) { + ByteArrays.validateBounds(array, offset, 3); + + if (bo == null) { + throw new NullPointerException(" bo: null"); + } + + if (bo.equals(LITTLE_ENDIAN)) { + return ((0xFF & array[offset + 2]) << (BYTE_SIZE_IN_BITS * 2)) + | ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1)) + | ((0xFF & array[offset])); + } else { + return ((0xFF & array[offset]) << (BYTE_SIZE_IN_BITS * 2)) + | ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1)) + | ((0xFF & array[offset + 2])); + } + } + /** * @param value value * @return byte array From ea9b7530985a53a913077a2ddf6ab9bf25d89bb1 Mon Sep 17 00:00:00 2001 From: serega6531 Date: Tue, 28 Apr 2020 17:09:04 +0300 Subject: [PATCH 02/10] TLS packets creating --- pcap4j-core/src/main/java/module-info.java | 8 ++ .../java/org/pcap4j/packet/TlsPacket.java | 4 +- .../packet/tls/extensions/TlsExtension.java | 3 + .../extensions/UnimplementedTlsExtension.java | 12 +++ .../keyshare/ClientKeyShareExtension.java | 14 ++- .../extensions/keyshare/KeyShareEntry.java | 11 +++ .../keyshare/KeyShareExtension.java | 11 +++ .../keyshare/ServerKeyShareExtension.java | 10 +++ .../packet/tls/records/AlertRecord.java | 8 ++ .../tls/records/ApplicationDataRecord.java | 4 + .../tls/records/ChangeCipherSpecRecord.java | 5 ++ .../packet/tls/records/HandshakeRecord.java | 11 +++ .../packet/tls/records/HeartbeatRecord.java | 18 ++++ .../pcap4j/packet/tls/records/TlsRecord.java | 2 + .../BasicHandshakeRecordContent.java | 5 ++ .../CertificateHandshakeRecordContent.java | 29 +++++++ .../ClientHelloHandshakeRecordContent.java | 55 +++++++++--- .../handshakes/HandshakeRecordContent.java | 3 + .../HelloHandshakeRecordContent.java | 21 +++++ .../ServerHelloHandshakeRecordContent.java | 29 +++++-- .../main/java/org/pcap4j/util/ByteArrays.java | 87 ++++++++++++------- .../tls/keys => util}/DhClientParams.java | 2 +- .../tls/keys => util}/EcdheServerParams.java | 2 +- .../tls/keys => util}/TlsKeyUtils.java | 8 +- 24 files changed, 303 insertions(+), 59 deletions(-) rename pcap4j-core/src/main/java/org/pcap4j/{packet/tls/keys => util}/DhClientParams.java (96%) rename pcap4j-core/src/main/java/org/pcap4j/{packet/tls/keys => util}/EcdheServerParams.java (96%) rename pcap4j-core/src/main/java/org/pcap4j/{packet/tls/keys => util}/TlsKeyUtils.java (96%) diff --git a/pcap4j-core/src/main/java/module-info.java b/pcap4j-core/src/main/java/module-info.java index 21728b8b3..5d63d612c 100644 --- a/pcap4j-core/src/main/java/module-info.java +++ b/pcap4j-core/src/main/java/module-info.java @@ -1,6 +1,14 @@ module org.pcap4j.core { exports org.pcap4j.core; exports org.pcap4j.packet; + + exports org.pcap4j.packet.tls.records; + exports org.pcap4j.packet.tls.records.handshakes; + exports org.pcap4j.packet.tls.extensions; + exports org.pcap4j.packet.tls.extensions.keyshare; + exports org.pcap4j.packet.tls.keys.enums; + exports org.pcap4j.packet.namednumber.tls; + exports org.pcap4j.packet.factory; exports org.pcap4j.packet.namednumber; exports org.pcap4j.packet.constant; diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java index 0873ee76e..848b6b993 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java @@ -93,7 +93,7 @@ private TlsHeader(Builder builder) { //TODO } - private TlsHeader(byte[] rawData, int offset, int length) throws IllegalRawDataException { + private TlsHeader(byte[] rawData, int offset, int length) { ByteArrays.validateBounds(rawData, offset, RECORD_OFFSET); this.contentType = ContentType.getInstance(ByteArrays.getByte(rawData, CONTENT_TYPE_OFFSET + offset)); this.version = TlsVersion.getInstance(ByteArrays.getShort(rawData, VERSION_OFFSET + offset)); @@ -132,7 +132,7 @@ protected List getRawFields() { rawFields.add(new byte[]{contentType.value()}); rawFields.add(ByteArrays.toByteArray(version.value())); rawFields.add(ByteArrays.toByteArray(recordLength)); - //TODO + rawFields.add(record.toByteArray()); return rawFields; } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java index b016c8866..86e09e3dd 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java @@ -46,4 +46,7 @@ public short getLength() { public String toString() { return type.name(); } + + public abstract byte[] toByteArray(); + } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java index cc6d8e7cc..a155071cb 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java @@ -1,6 +1,9 @@ package org.pcap4j.packet.tls.extensions; import org.pcap4j.packet.namednumber.tls.ExtensionType; +import org.pcap4j.util.ByteArrays; + +import java.util.Arrays; public class UnimplementedTlsExtension extends TlsExtension { @@ -21,4 +24,13 @@ public String toString() { return type.name(); } } + + @Override + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + ByteArrays.toByteArray(type.value()), + ByteArrays.toByteArray(extensionLength), + data + )); + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java index dae9a9c6a..adb13d5bc 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java @@ -1,7 +1,9 @@ package org.pcap4j.packet.tls.extensions.keyshare; -import org.pcap4j.util.ByteArrays; import org.pcap4j.packet.namednumber.tls.ExtensionType; +import org.pcap4j.util.ByteArrays; + +import java.util.Arrays; import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; @@ -14,10 +16,18 @@ public class ClientKeyShareExtension extends KeyShareExtension { public ClientKeyShareExtension(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 + this.keyShareLength = ByteArrays.getShort(rawData, KEY_SHARE_LENGTH_OFFSET + offset); int cursor = KEY_SHARE_ENTRY_OFFSET + offset; ByteArrays.validateBounds(rawData, cursor, keyShareLength); readEntries(rawData, KEY_SHARE_ENTRY_OFFSET + offset, offset + keyShareLength); } + @Override + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + ByteArrays.toByteArray(type.value()), + ByteArrays.toByteArray(extensionLength), + ByteArrays.toByteArray(keyShareLength), + entriesToByteArray())); + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java index ee4e348e9..8f503231c 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java @@ -3,6 +3,8 @@ import org.pcap4j.util.ByteArrays; import org.pcap4j.packet.namednumber.tls.KeyGroup; +import java.util.Arrays; + import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; public class KeyShareEntry { @@ -30,4 +32,13 @@ public int size() { public String toString() { return group.name(); } + + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + ByteArrays.toByteArray(group.value()), + ByteArrays.toByteArray(keyExhangeLength), + keyExchange + )); + } + } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java index 16829f863..5cffffd1b 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java @@ -43,4 +43,15 @@ protected KeyShareEntry readEntry(byte[] rawData, int cursor) { public String toString() { return type.name() + " " + entries.toString(); } + + protected byte[] entriesToByteArray() { + List list = new ArrayList<>(); + + for (KeyShareEntry entry : entries) { + list.add(entry.toByteArray()); + } + + return ByteArrays.concatenate(list); + } + } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java index a7aea49f5..9a69eaa36 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java @@ -1,6 +1,9 @@ package org.pcap4j.packet.tls.extensions.keyshare; import org.pcap4j.packet.namednumber.tls.ExtensionType; +import org.pcap4j.util.ByteArrays; + +import java.util.Arrays; public class ServerKeyShareExtension extends KeyShareExtension { @@ -11,4 +14,11 @@ public ServerKeyShareExtension(ExtensionType type, byte[] rawData, int offset, s readEntry(rawData, KEY_SHARE_ENTRY_OFFSET + offset); } + @Override + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + ByteArrays.toByteArray(type.value()), + ByteArrays.toByteArray(extensionLength), + entriesToByteArray())); + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java index 113591c8b..44766e420 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java @@ -34,4 +34,12 @@ public AlertRecord(byte[] rawData, int offset) { public String toString() { return " Alert [level: " + level.name() + ", description: " + description.name() + "]"; } + + @Override + public byte[] toByteArray() { + byte[] content = new byte[2]; + content[0] = level.value(); + content[1] = description.value(); + return content; + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java index 3cd16af52..56f33d958 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java @@ -30,4 +30,8 @@ public String toString() { return " Encrypted data: [" + data.length + " bytes]"; } + @Override + public byte[] toByteArray() { + return data; + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java index 1e9269848..4fa8f1886 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java @@ -24,4 +24,9 @@ private ChangeCipherSpecRecord(byte[] rawData, int offset) { public String toString() { return " Change Cipher Spec Message: " + changeCipherSpecMessage; } + + @Override + public byte[] toByteArray() { + return new byte[] { changeCipherSpecMessage }; + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java index 6a77f8f99..36c036fa5 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java @@ -4,6 +4,8 @@ import org.pcap4j.util.ByteArrays; import org.pcap4j.packet.namednumber.tls.HandshakeType; +import java.util.Arrays; + import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; public class HandshakeRecord implements TlsRecord { @@ -69,4 +71,13 @@ public String toString() { " Handshake type: " + handshakeType + "\n" + content.toString(); } + + @Override + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + ByteArrays.toByteArray(handshakeType.value()), + ByteArrays.toByteArray(handshakeLength), + content.toByteArray() + )); + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java index 75ebd1e3c..cee60350d 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java @@ -3,6 +3,8 @@ import org.pcap4j.util.ByteArrays; import org.pcap4j.packet.namednumber.tls.HeartbeatMessageType; +import java.util.Arrays; + import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; @@ -10,6 +12,13 @@ public class HeartbeatRecord implements TlsRecord { //https://tools.ietf.org/html/rfc6520 + /** + * 0x0 - type + * 0x1 - payload length + * 0x3 - payload + * 0x3+length - padding + */ + private static final int TYPE_OFFSET = 0; private static final int PAYLOAD_LENGTH_OFFSET = TYPE_OFFSET + BYTE_SIZE_IN_BYTES; private static final int PAYLOAD_OFFSET = PAYLOAD_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; @@ -50,4 +59,13 @@ public String toString() { padding.length + " bytes padding]"; } + @Override + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + ByteArrays.toByteArray(type.value()), + ByteArrays.toByteArray(payloadLength), + payload, + padding + )); + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/TlsRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/TlsRecord.java index acbeb3bbd..2ebda9601 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/TlsRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/TlsRecord.java @@ -4,4 +4,6 @@ public interface TlsRecord extends Serializable { + byte[] toByteArray(); + } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java index 9ee09016b..7b0d97cc0 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java @@ -33,4 +33,9 @@ public byte[] getContent() { public String toString() { return " [" + content.length + " bytes]"; } + + @Override + public byte[] toByteArray() { + return content; + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java index c71618676..867e6407c 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java @@ -3,10 +3,21 @@ import org.pcap4j.util.ByteArrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class CertificateHandshakeRecordContent implements HandshakeRecordContent { + /** + * 0x0 - Certificates length + * 0x3 - Certificate 1 + *

+ * Certificate: + * 0x0 - Certificate length (cl) + * 0x3 - Certificate data + * 0x3+cl - Next certificate + */ + private static final int CERTIFICATES_LENGTH_OFFSET = 0; private static final int CERTIFICATES_OFFSET = 3; @@ -48,4 +59,22 @@ public String toString() { return sb.toString(); } + @Override + public byte[] toByteArray() { + List list = new ArrayList<>(); + + list.add(ByteArrays.threeBytesIntToByteArray(certificatesLength)); + for (byte[] cert : rawCertificates) { + list.addAll(certificateToByteArray(cert)); + } + + return ByteArrays.concatenate(list); + } + + private List certificateToByteArray(byte[] certificate) { + return Arrays.asList( + ByteArrays.threeBytesIntToByteArray(certificate.length), + certificate + ); + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java index 8fd66e60f..f384e0a70 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java @@ -5,6 +5,7 @@ import org.pcap4j.packet.namednumber.tls.CompressionMethod; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; @@ -13,16 +14,17 @@ public class ClientHelloHandshakeRecordContent extends HelloHandshakeRecordContent { /* - 0x0 - Client random - 0x20 - Session id length (sidl) - 0x21 - Session id - 0x21+sidl - Cipher suites length (csl) - 0x23+sidl - Cipher suite 1..(csl/2) - 0x23+sidl+csl - Compression methods length (cml) - 0x24+sidl+csl - Compression method 1..cml - 0x24+sidl+csl+cml - Extensions Length (el) - 0x26+sidl+csl+cml - Extension 1..N - 0x26+sidl+csl+cml+el - End + 0x0 - TLS version + 0x2 - Client random + 0x22 - Session id length (sidl) + 0x23 - Session id + 0x23+sidl - Cipher suites length (csl) + 0x25+sidl - Cipher suite 1..(csl/2) + 0x25+sidl+csl - Compression methods length (cml) + 0x26+sidl+csl - Compression method 1..cml + 0x26+sidl+csl+cml - Extensions Length (el) + 0x28+sidl+csl+cml - Extension 1..N + 0x28+sidl+csl+cml+el - End */ private static final int CIPHER_SUITES_LENGTH_OFFSET = HelloHandshakeRecordContent.SESSION_ID_OFFSET; // + sessionIdLength @@ -79,4 +81,37 @@ public String toString() { " Cipher suites: " + cipherSuites.toString() + "\n" + " Compression methods: " + compressionMethods.toString(); } + + @Override + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + commonPartToByteArray(), + ByteArrays.toByteArray(cipherSuitesLength), + cipherSuitesToByteArray(), + ByteArrays.toByteArray(compressionMethodsLength), + compressionMethodsToByteArray(), + extensionsToByteArray() + )); + } + + private byte[] cipherSuitesToByteArray() { + List list = new ArrayList<>(); + + for (CipherSuite suite : cipherSuites) { + list.add(ByteArrays.toByteArray(suite.value())); + } + + return ByteArrays.concatenate(list); + } + + private byte[] compressionMethodsToByteArray() { + byte[] array = new byte[compressionMethods.size()]; + + for (int i = 0; i < compressionMethods.size(); i++) { + array[i] = compressionMethods.get(i).value(); + } + + return array; + } + } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java index c22d6456b..fc3723b45 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java @@ -1,4 +1,7 @@ package org.pcap4j.packet.tls.records.handshakes; public interface HandshakeRecordContent { + + byte[] toByteArray(); + } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java index dc129dba6..41cce9579 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java @@ -6,6 +6,7 @@ import org.pcap4j.packet.namednumber.tls.TlsVersion; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; @@ -78,4 +79,24 @@ public String toString() { " Session id: " + (sessionIdLength > 0 ? ByteArrays.toHexString(sessionId, "") : "null") + "\n" + " Extensions: " + extensions.toString(); } + + protected byte[] commonPartToByteArray() { + return ByteArrays.concatenate(Arrays.asList( + ByteArrays.toByteArray(version.value()), + random, + ByteArrays.toByteArray(sessionIdLength), + sessionId + )); + } + + protected byte[] extensionsToByteArray() { + List list = new ArrayList<>(); + + list.add(ByteArrays.toByteArray(extensionsLength)); + for (TlsExtension extension : extensions) { + list.add(extension.toByteArray()); + } + + return ByteArrays.concatenate(list); + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java index 0d2d0964f..85c20fb7c 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java @@ -4,20 +4,23 @@ import org.pcap4j.packet.namednumber.tls.CipherSuite; import org.pcap4j.packet.namednumber.tls.CompressionMethod; +import java.util.Arrays; + import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; public class ServerHelloHandshakeRecordContent extends HelloHandshakeRecordContent { /* - 0x0 - Server random - 0x20 - Session id length (sidl) - 0x21 - Session id - 0x21+si - Cipher suite - 0x23+sidl - Compression method - 0x24+sidl - Extensions Length (el) - 0x26+sidl - Extension 1..N - 0x26+sidl+el - End + 0x0 - TLS version + 0x2 - Server random + 0x22 - Session id length (sidl) + 0x23 - Session id + 0x23+si - Cipher suite + 0x25+sidl - Compression method + 0x26+sidl - Extensions Length (el) + 0x28+sidl - Extension 1..N + 0x28+sidl+el - End */ private static final int CIPHER_SUITE_OFFSET = HelloHandshakeRecordContent.SESSION_ID_OFFSET; // + sessionIdLength @@ -61,4 +64,14 @@ public String toString() { " Compression method: " + compressionMethod.toString(); } + @Override + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + commonPartToByteArray(), + ByteArrays.toByteArray(cipherSuite.value()), + ByteArrays.toByteArray(compressionMethod.value()), + ByteArrays.toByteArray(extensionsLength), + extensionsToByteArray() + )); + } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java b/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java index a03c1b5da..972842ac5 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java +++ b/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java @@ -314,39 +314,6 @@ public static int getInt(byte[] array, int offset, int length, ByteOrder bo) { return value; } - /** - * @param array array - * @param offset offset - * @return int value. - */ - public static int getThreeBytesInt(byte[] array, int offset) { - return getThreeBytesInt(array, offset, ByteOrder.BIG_ENDIAN); - } - - /** - * @param array array - * @param offset offset - * @param bo bo - * @return int value. - */ - public static int getThreeBytesInt(byte[] array, int offset, ByteOrder bo) { - ByteArrays.validateBounds(array, offset, 3); - - if (bo == null) { - throw new NullPointerException(" bo: null"); - } - - if (bo.equals(LITTLE_ENDIAN)) { - return ((0xFF & array[offset + 2]) << (BYTE_SIZE_IN_BITS * 2)) - | ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1)) - | ((0xFF & array[offset])); - } else { - return ((0xFF & array[offset]) << (BYTE_SIZE_IN_BITS * 2)) - | ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1)) - | ((0xFF & array[offset + 2])); - } - } - /** * @param value value * @return byte array @@ -437,6 +404,60 @@ public static String toHexString(int value, String separator, ByteOrder bo) { return toHexString(toByteArray(value, bo), separator); } + + /** + * @param array array + * @param offset offset + * @return int value. + */ + public static int getThreeBytesInt(byte[] array, int offset) { + return getThreeBytesInt(array, offset, ByteOrder.BIG_ENDIAN); + } + + /** + * @param array array + * @param offset offset + * @param bo bo + * @return int value. + */ + public static int getThreeBytesInt(byte[] array, int offset, ByteOrder bo) { + ByteArrays.validateBounds(array, offset, 3); + + if (bo == null) { + throw new NullPointerException(" bo: null"); + } + + if (bo.equals(LITTLE_ENDIAN)) { + return ((0xFF & array[offset + 2]) << (BYTE_SIZE_IN_BITS * 2)) + | ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1)) + | ((0xFF & array[offset])); + } else { + return ((0xFF & array[offset]) << (BYTE_SIZE_IN_BITS * 2)) + | ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1)) + | ((0xFF & array[offset + 2])); + } + } + + public static byte[] threeBytesIntToByteArray(int value) { + return threeBytesIntToByteArray(value, BIG_ENDIAN); + } + + public static byte[] threeBytesIntToByteArray(int value, ByteOrder bo) { + if (bo.equals(LITTLE_ENDIAN)) { + return new byte[] { + (byte) (value), + (byte) (value >> BYTE_SIZE_IN_BITS * 1), + (byte) (value >> BYTE_SIZE_IN_BITS * 2), + }; + } else { + return new byte[] { + (byte) (value >> BYTE_SIZE_IN_BITS * 2), + (byte) (value >> BYTE_SIZE_IN_BITS * 1), + (byte) (value) + }; + } + } + /** * @param array array * @param offset offset diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/DhClientParams.java b/pcap4j-core/src/main/java/org/pcap4j/util/DhClientParams.java similarity index 96% rename from pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/DhClientParams.java rename to pcap4j-core/src/main/java/org/pcap4j/util/DhClientParams.java index a8fc3321d..422fe1d3d 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/DhClientParams.java +++ b/pcap4j-core/src/main/java/org/pcap4j/util/DhClientParams.java @@ -1,4 +1,4 @@ -package org.pcap4j.packet.tls.keys; +package org.pcap4j.util; import org.pcap4j.packet.tls.keys.enums.SignatureScheme; diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/EcdheServerParams.java b/pcap4j-core/src/main/java/org/pcap4j/util/EcdheServerParams.java similarity index 96% rename from pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/EcdheServerParams.java rename to pcap4j-core/src/main/java/org/pcap4j/util/EcdheServerParams.java index 9b7fa9042..c89c321ed 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/EcdheServerParams.java +++ b/pcap4j-core/src/main/java/org/pcap4j/util/EcdheServerParams.java @@ -1,4 +1,4 @@ -package org.pcap4j.packet.tls.keys; +package org.pcap4j.util; import org.pcap4j.packet.tls.keys.enums.CurveType; import org.pcap4j.packet.tls.keys.enums.NamedCurve; diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/TlsKeyUtils.java b/pcap4j-core/src/main/java/org/pcap4j/util/TlsKeyUtils.java similarity index 96% rename from pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/TlsKeyUtils.java rename to pcap4j-core/src/main/java/org/pcap4j/util/TlsKeyUtils.java index 07f551632..73ee1c712 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/TlsKeyUtils.java +++ b/pcap4j-core/src/main/java/org/pcap4j/util/TlsKeyUtils.java @@ -1,4 +1,4 @@ -package org.pcap4j.packet.tls.keys; +package org.pcap4j.util; import org.pcap4j.packet.tls.keys.enums.CurveType; import org.pcap4j.packet.tls.keys.enums.NamedCurve; @@ -14,6 +14,9 @@ public final class TlsKeyUtils { // https://wiki.osdev.org/TLS_Handshake + private TlsKeyUtils() { + } + public static DhClientParams parseServerDH(byte[] rawData, int offset) { ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset); @@ -50,7 +53,7 @@ public static EcdheServerParams parseServerECDHE(byte[] rawData, int offset) { ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset); byte curveTypeId = bb.get(); - if(curveTypeId != 0x03) { + if (curveTypeId != 0x03) { throw new IllegalArgumentException("Unsupported curve type"); } @@ -83,6 +86,7 @@ public static EcdheServerParams parseServerECDHE(byte[] rawData, int offset) { /** * Suitable for both DH and ECDHE + * * @param rawData Handshake record content */ public static byte[] getClientDHPubkey(byte[] rawData, int offset) { From 69823fdc5362e7ec85c690dcc5bb4a95c05e39a9 Mon Sep 17 00:00:00 2001 From: serega6531 Date: Tue, 28 Apr 2020 19:58:18 +0300 Subject: [PATCH 03/10] Add builders and getters --- .../java/org/pcap4j/packet/TlsPacket.java | 48 ++++++++++++++++--- .../packet/tls/records/AlertRecord.java | 17 ++++++- .../tls/records/ApplicationDataRecord.java | 6 ++- .../tls/records/ChangeCipherSpecRecord.java | 10 +++- .../packet/tls/records/HandshakeRecord.java | 16 +++++-- .../packet/tls/records/HeartbeatRecord.java | 22 ++++++--- .../BasicHandshakeRecordContent.java | 6 ++- .../CertificateHandshakeRecordContent.java | 14 +++++- .../ClientHelloHandshakeRecordContent.java | 37 ++++++++++++-- .../HelloHandshakeRecordContent.java | 17 +++++++ .../ServerHelloHandshakeRecordContent.java | 15 +++++- 11 files changed, 179 insertions(+), 29 deletions(-) diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java index 848b6b993..0f28dd73b 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java @@ -84,13 +84,16 @@ public static final class TlsHeader extends AbstractHeader { private static final int LENGTH_OFFSET = VERSION_OFFSET + SHORT_SIZE_IN_BYTES; private static final int RECORD_OFFSET = LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; - private ContentType contentType; - private TlsVersion version; - private short recordLength; - private TlsRecord record; + private final ContentType contentType; + private final TlsVersion version; + private final short recordLength; + private final TlsRecord record; private TlsHeader(Builder builder) { - //TODO + this.contentType = builder.contentType; + this.version = builder.version; + this.recordLength = builder.recordLength; + this.record = builder.record; } private TlsHeader(byte[] rawData, int offset, int length) { @@ -122,6 +125,10 @@ public TlsVersion getVersion() { return version; } + public short getRecordLength() { + return recordLength; + } + public TlsRecord getRecord() { return record; } @@ -137,7 +144,7 @@ protected List getRawFields() { } @Override - public int length() { + protected int calcLength() { return RECORD_OFFSET + recordLength; } @@ -152,6 +159,11 @@ protected String buildString() { public static final class Builder extends AbstractBuilder { + private ContentType contentType; + private TlsVersion version; + private short recordLength; + private TlsRecord record; + private Packet.Builder payloadBuilder; public Builder() { @@ -159,6 +171,30 @@ public Builder() { public Builder(TlsPacket packet) { this.payloadBuilder = packet.payload != null ? packet.payload.getBuilder() : null; + this.contentType = packet.header.contentType; + this.version = packet.header.version; + this.recordLength = packet.header.recordLength; + this.record = packet.header.record; + } + + public Builder contentType(ContentType contentType) { + this.contentType = contentType; + return this; + } + + public Builder version(TlsVersion version) { + this.version = version; + return this; + } + + public Builder recordLength(short recordLength) { + this.recordLength = recordLength; + return this; + } + + public Builder record(TlsRecord record) { + this.record = record; + return this; } @Override diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java index 44766e420..a768b3c8c 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java @@ -17,8 +17,8 @@ public class AlertRecord implements TlsRecord { private static final int LEVEL_OFFSET = 0; private static final int DESCRIPTION_OFFSET = LEVEL_OFFSET + BYTE_SIZE_IN_BYTES; - private AlertLevel level; - private AlertDescription description; + private final AlertLevel level; + private final AlertDescription description; public static AlertRecord newInstance(byte[] rawData, int offset, int length) { ByteArrays.validateBounds(rawData, offset, length); @@ -30,6 +30,19 @@ public AlertRecord(byte[] rawData, int offset) { this.description = AlertDescription.getInstance(ByteArrays.getByte(rawData, DESCRIPTION_OFFSET + offset)); } + public AlertRecord(AlertLevel level, AlertDescription description) { + this.level = level; + this.description = description; + } + + public AlertLevel getLevel() { + return level; + } + + public AlertDescription getDescription() { + return description; + } + @Override public String toString() { return " Alert [level: " + level.name() + ", description: " + description.name() + "]"; diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java index 56f33d958..50bb45782 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java @@ -9,7 +9,7 @@ public class ApplicationDataRecord implements TlsRecord { * 0x0 + length - End */ - private byte[] data; + private final byte[] data; public static ApplicationDataRecord newInstance(byte[] rawData, int offset, int length) { ByteArrays.validateBounds(rawData, offset, length); @@ -21,6 +21,10 @@ public ApplicationDataRecord(byte[] rawData, int offset, int length) { System.arraycopy(rawData, offset, data, 0, length); } + public ApplicationDataRecord(byte[] data) { + this.data = data; + } + public byte[] getData() { return data; } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java index 4fa8f1886..ccc6dd6c1 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java @@ -9,7 +9,7 @@ public class ChangeCipherSpecRecord implements TlsRecord { 0x1 - End */ - private byte changeCipherSpecMessage; + private final byte changeCipherSpecMessage; public static ChangeCipherSpecRecord newInstance(byte[] rawData, int offset, int length) { ByteArrays.validateBounds(rawData, offset, length); @@ -20,6 +20,14 @@ private ChangeCipherSpecRecord(byte[] rawData, int offset) { this.changeCipherSpecMessage = ByteArrays.getByte(rawData, offset); } + public ChangeCipherSpecRecord(byte changeCipherSpecMessage) { + this.changeCipherSpecMessage = changeCipherSpecMessage; + } + + public byte getChangeCipherSpecMessage() { + return changeCipherSpecMessage; + } + @Override public String toString() { return " Change Cipher Spec Message: " + changeCipherSpecMessage; diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java index 36c036fa5..ef89da33b 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java @@ -21,9 +21,9 @@ public class HandshakeRecord implements TlsRecord { 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; + private final HandshakeType handshakeType; + private final int handshakeLength; // 3 bytes + private final HandshakeRecordContent content; public static HandshakeRecord newInstance(byte[] rawData, int offset, int length) { ByteArrays.validateBounds(rawData, offset, length); @@ -57,10 +57,20 @@ private HandshakeRecord(byte[] rawData, int offset, int length) { } } + public HandshakeRecord(HandshakeType handshakeType, int handshakeLength, HandshakeRecordContent content) { + this.handshakeType = handshakeType; + this.handshakeLength = handshakeLength; + this.content = content; + } + public HandshakeType getHandshakeType() { return handshakeType; } + public int getHandshakeLength() { + return handshakeLength; + } + public HandshakeRecordContent getContent() { return content; } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java index cee60350d..8b66ef9d3 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java @@ -1,7 +1,7 @@ package org.pcap4j.packet.tls.records; -import org.pcap4j.util.ByteArrays; import org.pcap4j.packet.namednumber.tls.HeartbeatMessageType; +import org.pcap4j.util.ByteArrays; import java.util.Arrays; @@ -23,23 +23,30 @@ public class HeartbeatRecord implements TlsRecord { private static final int PAYLOAD_LENGTH_OFFSET = TYPE_OFFSET + BYTE_SIZE_IN_BYTES; private static final int PAYLOAD_OFFSET = PAYLOAD_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; - private HeartbeatMessageType type; - private short payloadLength; - private byte[] payload; - private byte[] padding; + private final HeartbeatMessageType type; + private final short payloadLength; + private final byte[] payload; + private final byte[] padding; public static HeartbeatRecord newInstance(byte[] rawData, int offset, int length) { ByteArrays.validateBounds(rawData, offset, length); - return new HeartbeatRecord(rawData, offset, length); + return new HeartbeatRecord(rawData, offset); } - public HeartbeatRecord(byte[] rawData, int offset, int length) { + public HeartbeatRecord(byte[] rawData, int offset) { this.type = HeartbeatMessageType.getInstance(ByteArrays.getByte(rawData, TYPE_OFFSET + offset)); this.payloadLength = ByteArrays.getShort(rawData, PAYLOAD_LENGTH_OFFSET + offset); this.payload = ByteArrays.getSubArray(rawData, PAYLOAD_OFFSET + offset, payloadLength); this.padding = ByteArrays.getSubArray(rawData, PAYLOAD_OFFSET + payloadLength + offset); } + public HeartbeatRecord(HeartbeatMessageType type, short payloadLength, byte[] payload, byte[] padding) { + this.type = type; + this.payloadLength = payloadLength; + this.payload = payload; + this.padding = padding; + } + public HeartbeatMessageType getType() { return type; } @@ -68,4 +75,5 @@ public byte[] toByteArray() { padding )); } + } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java index 7b0d97cc0..99dd9e183 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java @@ -9,7 +9,7 @@ public class BasicHandshakeRecordContent implements HandshakeRecordContent { * 0x0 + length - End */ - private byte[] content; + private final byte[] content; public static BasicHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { if(length > 0) { @@ -25,6 +25,10 @@ public BasicHandshakeRecordContent(byte[] rawData, int offset, int length) { } } + public BasicHandshakeRecordContent(byte[] content) { + this.content = content; + } + public byte[] getContent() { return content; } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java index 867e6407c..57c66ff13 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java @@ -21,8 +21,8 @@ public class CertificateHandshakeRecordContent implements HandshakeRecordContent private static final int CERTIFICATES_LENGTH_OFFSET = 0; private static final int CERTIFICATES_OFFSET = 3; - private int certificatesLength; - private List rawCertificates = new ArrayList<>(); + private final int certificatesLength; + private final List rawCertificates; public static CertificateHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { return new CertificateHandshakeRecordContent(rawData, offset, length); @@ -30,6 +30,7 @@ public static CertificateHandshakeRecordContent newInstance(byte[] rawData, int public CertificateHandshakeRecordContent(byte[] rawData, int offset, int length) { this.certificatesLength = ByteArrays.getThreeBytesInt(rawData, CERTIFICATES_LENGTH_OFFSET + offset); + this.rawCertificates = new ArrayList<>(); int cursor = CERTIFICATES_OFFSET + offset; while (cursor < offset + length) { @@ -43,6 +44,15 @@ public CertificateHandshakeRecordContent(byte[] rawData, int offset, int length) } } + public CertificateHandshakeRecordContent(int certificatesLength, List rawCertificates) { + this.certificatesLength = certificatesLength; + this.rawCertificates = rawCertificates; + } + + public int getCertificatesLength() { + return certificatesLength; + } + public List getRawCertificates() { return rawCertificates; } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java index f384e0a70..7d06a0b58 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java @@ -1,5 +1,7 @@ package org.pcap4j.packet.tls.records.handshakes; +import org.pcap4j.packet.namednumber.tls.TlsVersion; +import org.pcap4j.packet.tls.extensions.TlsExtension; import org.pcap4j.util.ByteArrays; import org.pcap4j.packet.namednumber.tls.CipherSuite; import org.pcap4j.packet.namednumber.tls.CompressionMethod; @@ -37,10 +39,10 @@ public class ClientHelloHandshakeRecordContent extends HelloHandshakeRecordConte COMPRESSION_METHOD_OFFSET; // + sessionIdLength + cipherSuitesLength + compressionMethodsLength private static final int EXTENSIONS_OFFSET = COMPRESSION_METHOD_OFFSET + SHORT_SIZE_IN_BYTES; - private short cipherSuitesLength; - private List cipherSuites; - private byte compressionMethodsLength; - private List compressionMethods; + private final short cipherSuitesLength; + private final List cipherSuites; + private final byte compressionMethodsLength; + private final List compressionMethods; public static ClientHelloHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { ByteArrays.validateBounds(rawData, offset, length); @@ -75,6 +77,33 @@ private ClientHelloHandshakeRecordContent(byte[] rawData, int offset) { sessionIdLength + cipherSuitesLength + offset, true); } + public ClientHelloHandshakeRecordContent(TlsVersion version, byte[] random, byte[] sessionId, + short extensionsLength, List extensions, + List cipherSuites, + List compressionMethods) { + super(version, random, sessionId, extensionsLength, extensions); + this.cipherSuitesLength = (short) (cipherSuites.size() * SHORT_SIZE_IN_BYTES); + this.cipherSuites = cipherSuites; + this.compressionMethodsLength = (byte) compressionMethods.size(); + this.compressionMethods = compressionMethods; + } + + public short getCipherSuitesLength() { + return cipherSuitesLength; + } + + public List getCipherSuites() { + return cipherSuites; + } + + public byte getCompressionMethodsLength() { + return compressionMethodsLength; + } + + public List getCompressionMethods() { + return compressionMethods; + } + @Override public String toString() { return super.toString() + "\n" + diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java index 41cce9579..30d1edc86 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java @@ -27,6 +27,19 @@ public abstract class HelloHandshakeRecordContent implements HandshakeRecordCont protected short extensionsLength; private List extensions; + protected HelloHandshakeRecordContent(){ + } + + public HelloHandshakeRecordContent(TlsVersion version, byte[] random, byte[] sessionId, + short extensionsLength, List extensions) { + this.version = version; + this.random = random; + this.sessionIdLength = (byte) sessionId.length; + this.sessionId = sessionId; + this.extensionsLength = extensionsLength; + this.extensions = extensions; + } + protected void readCommonPart(byte[] rawData, int offset) { this.version = TlsVersion.getInstance(ByteArrays.getShort(rawData, VERSION_OFFSET + offset)); System.arraycopy(rawData, RANDOM_OFFSET + offset, random, 0, 32); @@ -68,6 +81,10 @@ public byte[] getSessionId() { return sessionId; } + public short getExtensionsLength() { + return extensionsLength; + } + public List getExtensions() { return extensions; } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java index 85c20fb7c..6645abb4b 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java @@ -1,10 +1,13 @@ package org.pcap4j.packet.tls.records.handshakes; +import org.pcap4j.packet.namednumber.tls.TlsVersion; +import org.pcap4j.packet.tls.extensions.TlsExtension; import org.pcap4j.util.ByteArrays; import org.pcap4j.packet.namednumber.tls.CipherSuite; import org.pcap4j.packet.namednumber.tls.CompressionMethod; import java.util.Arrays; +import java.util.List; import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; @@ -28,8 +31,8 @@ public class ServerHelloHandshakeRecordContent extends HelloHandshakeRecordConte private static final int EXTENSIONS_LENGTH_OFFSET = COMPRESSION_METHOD_OFFSET + BYTE_SIZE_IN_BYTES; // + sessionIdLength private static final int EXTENSIONS_OFFSET = EXTENSIONS_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; // + sessionIdLength - private CipherSuite cipherSuite; - private CompressionMethod compressionMethod; + private final CipherSuite cipherSuite; + private final CompressionMethod compressionMethod; public static ServerHelloHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) { ByteArrays.validateBounds(rawData, offset, length); @@ -49,6 +52,14 @@ public ServerHelloHandshakeRecordContent(byte[] rawData, int offset) { readExtensions(rawData, EXTENSIONS_OFFSET + sessionIdLength + offset, false); } + public ServerHelloHandshakeRecordContent(TlsVersion version, byte[] random, byte[] sessionId, + short extensionsLength, List extensions, + CipherSuite cipherSuite, CompressionMethod compressionMethod) { + super(version, random, sessionId, extensionsLength, extensions); + this.cipherSuite = cipherSuite; + this.compressionMethod = compressionMethod; + } + public CipherSuite getCipherSuite() { return cipherSuite; } From 5de3ae7a0c07f31223185c6c00d2bdbb1301dc94 Mon Sep 17 00:00:00 2001 From: serega6531 Date: Fri, 8 May 2020 22:59:20 +0300 Subject: [PATCH 04/10] Fix encrypted alerts --- .../packet/namednumber/tls/AlertLevel.java | 8 ++-- .../packet/tls/records/AlertRecord.java | 44 +++++++++---------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java index 43ff234d0..14e381bcc 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java @@ -13,17 +13,15 @@ public class AlertLevel extends NamedNumber { public static final AlertLevel WARNING = new AlertLevel((byte) 1, "warning"); public static final AlertLevel FATAL = new AlertLevel((byte) 2, "fatal"); + public static final AlertLevel ENCRYPTED_ALERT = new AlertLevel((byte) 0, "encrypted alert"); + public AlertLevel(Byte value, String name) { super(value, name); registry.put(value, this); } public static AlertLevel getInstance(Byte value) { - if (registry.containsKey(value)) { - return registry.get(value); - } else { - throw new IllegalArgumentException("Unknown alert level: " + value); - } + return registry.getOrDefault(value, ENCRYPTED_ALERT); } @Override diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java index a768b3c8c..f653f72d4 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java @@ -17,42 +17,38 @@ public class AlertRecord implements TlsRecord { private static final int LEVEL_OFFSET = 0; private static final int DESCRIPTION_OFFSET = LEVEL_OFFSET + BYTE_SIZE_IN_BYTES; - private final AlertLevel level; - private final AlertDescription description; + private int length; + private byte[] content; + + private AlertLevel level; + private AlertDescription description; public static AlertRecord newInstance(byte[] rawData, int offset, int length) { ByteArrays.validateBounds(rawData, offset, length); - return new AlertRecord(rawData, offset); + return new AlertRecord(rawData, offset, length); } - public AlertRecord(byte[] rawData, int offset) { + public AlertRecord(byte[] rawData, int offset, int length) { + this.length = length; + this.content = ByteArrays.getSubArray(rawData, offset, length); this.level = AlertLevel.getInstance(ByteArrays.getByte(rawData, LEVEL_OFFSET + offset)); - this.description = AlertDescription.getInstance(ByteArrays.getByte(rawData, DESCRIPTION_OFFSET + offset)); - } - - public AlertRecord(AlertLevel level, AlertDescription description) { - this.level = level; - this.description = description; - } - - public AlertLevel getLevel() { - return level; - } - public AlertDescription getDescription() { - return description; + if (level != AlertLevel.ENCRYPTED_ALERT) { + this.description = AlertDescription.getInstance(ByteArrays.getByte(rawData, DESCRIPTION_OFFSET + offset)); + } } @Override - public String toString() { - return " Alert [level: " + level.name() + ", description: " + description.name() + "]"; + public byte[] toByteArray() { + return content; } @Override - public byte[] toByteArray() { - byte[] content = new byte[2]; - content[0] = level.value(); - content[1] = description.value(); - return content; + public String toString() { + if (level != AlertLevel.ENCRYPTED_ALERT) { + return " Alert [level: " + level.name() + ", description: " + description.name() + "]"; + } else { + return " Encrypted Alert [" + length + " bytes]"; + } } } From 56dd15a312f44fd63974e89f243697e70874d669 Mon Sep 17 00:00:00 2001 From: serega6531 Date: Fri, 8 May 2020 23:04:06 +0300 Subject: [PATCH 05/10] Add constructor for AlertRecord --- .../packet/tls/records/AlertRecord.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java index f653f72d4..22b625c05 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java @@ -17,7 +17,6 @@ public class AlertRecord implements TlsRecord { private static final int LEVEL_OFFSET = 0; private static final int DESCRIPTION_OFFSET = LEVEL_OFFSET + BYTE_SIZE_IN_BYTES; - private int length; private byte[] content; private AlertLevel level; @@ -29,7 +28,6 @@ public static AlertRecord newInstance(byte[] rawData, int offset, int length) { } public AlertRecord(byte[] rawData, int offset, int length) { - this.length = length; this.content = ByteArrays.getSubArray(rawData, offset, length); this.level = AlertLevel.getInstance(ByteArrays.getByte(rawData, LEVEL_OFFSET + offset)); @@ -38,6 +36,23 @@ public AlertRecord(byte[] rawData, int offset, int length) { } } + /** + * Encrypted alert constructor + */ + public AlertRecord(byte[] content) { + this.content = content; + this.level = AlertLevel.ENCRYPTED_ALERT; + } + + public AlertRecord(AlertLevel level, AlertDescription description) { + this.level = level; + this.description = description; + + content = new byte[2]; + content[0] = level.value(); + content[1] = description.value(); + } + @Override public byte[] toByteArray() { return content; @@ -48,7 +63,7 @@ public String toString() { if (level != AlertLevel.ENCRYPTED_ALERT) { return " Alert [level: " + level.name() + ", description: " + description.name() + "]"; } else { - return " Encrypted Alert [" + length + " bytes]"; + return " Encrypted Alert [" + content.length + " bytes]"; } } } From 004b66b143b594400335ffb78c60a6317db609e7 Mon Sep 17 00:00:00 2001 From: serega6531 Date: Sat, 9 May 2020 20:57:55 +0300 Subject: [PATCH 06/10] Remove usages from Java 7+ --- .../src/main/java/org/pcap4j/packet/TlsPacket.java | 2 +- .../pcap4j/packet/namednumber/tls/AlertDescription.java | 2 +- .../org/pcap4j/packet/namednumber/tls/AlertLevel.java | 8 ++++++-- .../org/pcap4j/packet/namednumber/tls/CipherSuite.java | 2 +- .../pcap4j/packet/namednumber/tls/CompressionMethod.java | 2 +- .../org/pcap4j/packet/namednumber/tls/ContentType.java | 2 +- .../org/pcap4j/packet/namednumber/tls/ExtensionType.java | 2 +- .../org/pcap4j/packet/namednumber/tls/HandshakeType.java | 8 ++++++-- .../packet/namednumber/tls/HeartbeatMessageType.java | 2 +- .../java/org/pcap4j/packet/namednumber/tls/KeyGroup.java | 2 +- .../org/pcap4j/packet/namednumber/tls/TlsVersion.java | 2 +- .../packet/tls/extensions/keyshare/KeyShareExtension.java | 4 ++-- .../java/org/pcap4j/packet/tls/keys/enums/NamedCurve.java | 2 +- .../org/pcap4j/packet/tls/keys/enums/SignatureScheme.java | 2 +- .../handshakes/CertificateHandshakeRecordContent.java | 4 ++-- .../handshakes/ClientHelloHandshakeRecordContent.java | 6 +++--- .../records/handshakes/HelloHandshakeRecordContent.java | 4 ++-- 17 files changed, 32 insertions(+), 24 deletions(-) diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java index 0f28dd73b..7a7997c35 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java @@ -135,7 +135,7 @@ public TlsRecord getRecord() { @Override protected List getRawFields() { - List rawFields = new ArrayList<>(); + List rawFields = new ArrayList(); rawFields.add(new byte[]{contentType.value()}); rawFields.add(ByteArrays.toByteArray(version.value())); rawFields.add(ByteArrays.toByteArray(recordLength)); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertDescription.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertDescription.java index 65abc043d..de6b6a645 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertDescription.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertDescription.java @@ -7,7 +7,7 @@ public class AlertDescription extends NamedNumber { - private static final Map registry = new HashMap<>(); + private static final Map registry = new HashMap(); // https://techcommunity.microsoft.com/t5/iis-support-blog/ssl-tls-alert-protocol-and-the-alert-codes/ba-p/377132 diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java index 14e381bcc..505cb731d 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java @@ -8,7 +8,7 @@ @SuppressWarnings("unused") public class AlertLevel extends NamedNumber { - private static final Map registry = new HashMap<>(); + private static final Map registry = new HashMap(); public static final AlertLevel WARNING = new AlertLevel((byte) 1, "warning"); public static final AlertLevel FATAL = new AlertLevel((byte) 2, "fatal"); @@ -21,7 +21,11 @@ public AlertLevel(Byte value, String name) { } public static AlertLevel getInstance(Byte value) { - return registry.getOrDefault(value, ENCRYPTED_ALERT); + if (registry.containsKey(value)) { + return registry.get(value); + } else { + return ENCRYPTED_ALERT; + } } @Override diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CipherSuite.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CipherSuite.java index 69fa6b2fa..29b7c5eca 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CipherSuite.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CipherSuite.java @@ -8,7 +8,7 @@ @SuppressWarnings("unused") public class CipherSuite extends NamedNumber { - private static final Map registry = new HashMap<>(); + private static final Map registry = new HashMap(); // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CompressionMethod.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CompressionMethod.java index 731dd054d..a008312bd 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CompressionMethod.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/CompressionMethod.java @@ -13,7 +13,7 @@ public class CompressionMethod extends NamedNumber { public static final CompressionMethod DEFLATE = new CompressionMethod((byte) 1, "Deflate"); public static final CompressionMethod LZS = new CompressionMethod((byte) 64, "LZS"); - private static final Map registry = new HashMap<>(); + private static final Map registry = new HashMap(); static { registry.put(NULL.value(), NULL); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ContentType.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ContentType.java index cb14f9af7..ff70bd700 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ContentType.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ContentType.java @@ -15,7 +15,7 @@ public class ContentType extends NamedNumber { 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<>(); + private static final Map registry = new HashMap(); static { registry.put(CHANGE_CIPHER_SPEC.value(), CHANGE_CIPHER_SPEC); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ExtensionType.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ExtensionType.java index 8c3504944..eff32c6f8 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ExtensionType.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/ExtensionType.java @@ -8,7 +8,7 @@ @SuppressWarnings("unused") public class ExtensionType extends NamedNumber { - private static final Map registry = new HashMap<>(); + private static final Map registry = new HashMap(); public static final ExtensionType SERVER_NAME = new ExtensionType((short) 0, "server_name"); public static final ExtensionType MAX_FRAGMENT_LENGTH = new ExtensionType((short) 1, "max_fragment_length"); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HandshakeType.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HandshakeType.java index 690733414..1c69fbe0d 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HandshakeType.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HandshakeType.java @@ -8,7 +8,7 @@ @SuppressWarnings("unused") public class HandshakeType extends NamedNumber { - private static final Map registry = new HashMap<>(); + private static final Map registry = new HashMap(); // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml @@ -42,7 +42,11 @@ public HandshakeType(Byte value, String name) { } public static HandshakeType getInstance(Byte value) { - return registry.getOrDefault(value, ENCRYPTED_HANDSHAKE_MESSAGE); + if (registry.containsKey(value)) { + return registry.get(value); + } else { + return ENCRYPTED_HANDSHAKE_MESSAGE; + } } @Override diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HeartbeatMessageType.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HeartbeatMessageType.java index 3b7fd4fb9..046375b19 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HeartbeatMessageType.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HeartbeatMessageType.java @@ -7,7 +7,7 @@ public class HeartbeatMessageType extends NamedNumber { - private static final Map registry = new HashMap<>(); + private static final Map registry = new HashMap(); public static final HeartbeatMessageType HEARTBEAT_REQUEST = new HeartbeatMessageType((byte) 1, "heartbeat_request"); public static final HeartbeatMessageType HEARTBEAT_RESPONSE = new HeartbeatMessageType((byte) 2, "heartbeat_response"); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/KeyGroup.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/KeyGroup.java index a097fe481..232be24c7 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/KeyGroup.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/KeyGroup.java @@ -10,7 +10,7 @@ public class KeyGroup extends NamedNumber { // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml - private static final Map registry = new HashMap<>(); + 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"); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/TlsVersion.java b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/TlsVersion.java index cb0cf2bdb..5b3a5d9b1 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/TlsVersion.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/TlsVersion.java @@ -12,7 +12,7 @@ public class TlsVersion extends NamedNumber { public static final TlsVersion TLS_1_2 = new TlsVersion((short) 0x0303, "TLS 1.2"); public static final TlsVersion TLS_1_3 = new TlsVersion((short) 0x0304, "TLS 1.3"); - private static final Map registry = new HashMap<>(); + private static final Map registry = new HashMap(); static { registry.put(TLS_1_0.value(), TLS_1_0); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java index 5cffffd1b..a8f00afd1 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java @@ -9,7 +9,7 @@ public abstract class KeyShareExtension extends TlsExtension { - private final List entries = new ArrayList<>(); + private final List entries = new ArrayList(); public static KeyShareExtension newInstance(ExtensionType type, byte[] rawData, int offset, short extensionLength, boolean client) { @@ -45,7 +45,7 @@ public String toString() { } protected byte[] entriesToByteArray() { - List list = new ArrayList<>(); + List list = new ArrayList(); for (KeyShareEntry entry : entries) { list.add(entry.toByteArray()); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/NamedCurve.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/NamedCurve.java index 00f248773..ab6bbb4f5 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/NamedCurve.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/NamedCurve.java @@ -35,7 +35,7 @@ public enum NamedCurve { private final short value; - private static final Map map = new HashMap<>(); + private static final Map map = new HashMap(); NamedCurve(short value) { this.value = value; diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/SignatureScheme.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/SignatureScheme.java index 452c6f1fc..1429d0b0f 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/SignatureScheme.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/keys/enums/SignatureScheme.java @@ -35,7 +35,7 @@ public enum SignatureScheme { private final short value; - private static final Map map = new HashMap<>(); + private static final Map map = new HashMap(); SignatureScheme(short value) { this.value = value; diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java index 57c66ff13..1df71f68d 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java @@ -30,7 +30,7 @@ public static CertificateHandshakeRecordContent newInstance(byte[] rawData, int public CertificateHandshakeRecordContent(byte[] rawData, int offset, int length) { this.certificatesLength = ByteArrays.getThreeBytesInt(rawData, CERTIFICATES_LENGTH_OFFSET + offset); - this.rawCertificates = new ArrayList<>(); + this.rawCertificates = new ArrayList(); int cursor = CERTIFICATES_OFFSET + offset; while (cursor < offset + length) { @@ -71,7 +71,7 @@ public String toString() { @Override public byte[] toByteArray() { - List list = new ArrayList<>(); + List list = new ArrayList(); list.add(ByteArrays.threeBytesIntToByteArray(certificatesLength)); for (byte[] cert : rawCertificates) { diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java index 7d06a0b58..73d18aea7 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java @@ -54,7 +54,7 @@ private ClientHelloHandshakeRecordContent(byte[] rawData, int offset) { this.cipherSuitesLength = ByteArrays.getShort(rawData, CIPHER_SUITES_LENGTH_OFFSET + sessionIdLength + offset); int cipherSuitesAmount = cipherSuitesLength / SHORT_SIZE_IN_BYTES; - this.cipherSuites = new ArrayList<>(cipherSuitesAmount); + this.cipherSuites = new ArrayList(cipherSuitesAmount); for (int i = 0; i < cipherSuitesAmount; i++) { this.cipherSuites.add(CipherSuite.getInstance(ByteArrays.getShort(rawData, @@ -63,7 +63,7 @@ private ClientHelloHandshakeRecordContent(byte[] rawData, int offset) { this.compressionMethodsLength = ByteArrays.getByte(rawData, COMPRESSION_METHODS_LENGTH_OFFSET + cipherSuitesLength + sessionIdLength + offset); - this.compressionMethods = new ArrayList<>(compressionMethodsLength); + this.compressionMethods = new ArrayList(compressionMethodsLength); for (byte i = 0; i < compressionMethodsLength; i++) { this.compressionMethods.add(CompressionMethod.getInstance(ByteArrays.getByte(rawData, @@ -124,7 +124,7 @@ public byte[] toByteArray() { } private byte[] cipherSuitesToByteArray() { - List list = new ArrayList<>(); + List list = new ArrayList(); for (CipherSuite suite : cipherSuites) { list.add(ByteArrays.toByteArray(suite.value())); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java index 30d1edc86..5ff48965a 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java @@ -52,7 +52,7 @@ protected void readCommonPart(byte[] rawData, int offset) { } protected void readExtensions(byte[] rawData, int offset, boolean client) { - extensions = new ArrayList<>(extensionsLength); + extensions = new ArrayList(extensionsLength); int cursor = offset; int extensionsEnd = cursor + extensionsLength; @@ -107,7 +107,7 @@ protected byte[] commonPartToByteArray() { } protected byte[] extensionsToByteArray() { - List list = new ArrayList<>(); + List list = new ArrayList(); list.add(ByteArrays.toByteArray(extensionsLength)); for (TlsExtension extension : extensions) { From d17b31fb09606a59e6f866d84339b5f716fde501 Mon Sep 17 00:00:00 2001 From: serega6531 Date: Sun, 10 May 2020 16:31:34 +0300 Subject: [PATCH 07/10] Add tests for TlsPacket, bugfixes --- .../java/org/pcap4j/packet/TlsPacket.java | 4 +- .../packet/tls/extensions/TlsExtension.java | 4 +- .../extensions/UnimplementedTlsExtension.java | 5 + .../packet/tls/records/HandshakeRecord.java | 2 +- .../handshakes/HandshakeRecordContent.java | 4 +- .../ServerHelloHandshakeRecordContent.java | 3 +- .../org/pcap4j/test/packet/TlsPacketTest.java | 212 ++++++++++++++++++ .../src/test/resources/TlsPacketTest.log | 11 + .../src/test/resources/TlsPacketTest.obj | Bin 0 -> 4387 bytes .../src/test/resources/TlsPacketTest.pcap | Bin 0 -> 182 bytes 10 files changed, 238 insertions(+), 7 deletions(-) create mode 100644 pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java create mode 100644 pcap4j-packettest/src/test/resources/TlsPacketTest.log create mode 100644 pcap4j-packettest/src/test/resources/TlsPacketTest.obj create mode 100644 pcap4j-packettest/src/test/resources/TlsPacketTest.pcap diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java index 7a7997c35..a71a22f82 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java @@ -150,7 +150,7 @@ protected int calcLength() { @Override protected String buildString() { - return "TLS Header [" + length() + " bytes]\n" + + return "[TLS Header (" + length() + " bytes)]\n" + " Version: " + version + "\n" + " Type: " + contentType + "\n" + record.toString(); @@ -198,7 +198,7 @@ public Builder record(TlsRecord record) { } @Override - public Packet build() { + public TlsPacket build() { return new TlsPacket(this); } } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java index 86e09e3dd..6c3855cf8 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java @@ -4,7 +4,9 @@ import org.pcap4j.packet.tls.extensions.keyshare.KeyShareExtension; import org.pcap4j.util.ByteArrays; -public abstract class TlsExtension { +import java.io.Serializable; + +public abstract class TlsExtension implements Serializable { /* 0x0 - Type diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java index a155071cb..32e963bd3 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java @@ -16,6 +16,11 @@ public UnimplementedTlsExtension(ExtensionType type, byte[] rawData, int offset, System.arraycopy(rawData, offset, data, 0, extensionLength); } + public UnimplementedTlsExtension(ExtensionType type, short extensionLength, byte[] data) { + super(type, extensionLength); + this.data = data; + } + @Override public String toString() { if(extensionLength > 0) { diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java index ef89da33b..e2c837d06 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java @@ -86,7 +86,7 @@ public String toString() { public byte[] toByteArray() { return ByteArrays.concatenate(Arrays.asList( ByteArrays.toByteArray(handshakeType.value()), - ByteArrays.toByteArray(handshakeLength), + ByteArrays.threeBytesIntToByteArray(handshakeLength), content.toByteArray() )); } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java index fc3723b45..8ea540992 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java @@ -1,6 +1,8 @@ package org.pcap4j.packet.tls.records.handshakes; -public interface HandshakeRecordContent { +import java.io.Serializable; + +public interface HandshakeRecordContent extends Serializable { byte[] toByteArray(); diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java index 6645abb4b..d7fa1f38d 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java @@ -19,7 +19,7 @@ public class ServerHelloHandshakeRecordContent extends HelloHandshakeRecordConte 0x2 - Server random 0x22 - Session id length (sidl) 0x23 - Session id - 0x23+si - Cipher suite + 0x23+sidl - Cipher suite 0x25+sidl - Compression method 0x26+sidl - Extensions Length (el) 0x28+sidl - Extension 1..N @@ -81,7 +81,6 @@ public byte[] toByteArray() { commonPartToByteArray(), ByteArrays.toByteArray(cipherSuite.value()), ByteArrays.toByteArray(compressionMethod.value()), - ByteArrays.toByteArray(extensionsLength), extensionsToByteArray() )); } diff --git a/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java b/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java new file mode 100644 index 000000000..c0399005c --- /dev/null +++ b/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java @@ -0,0 +1,212 @@ +package org.pcap4j.test.packet; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.pcap4j.core.PcapDumper; +import org.pcap4j.core.PcapHandle; +import org.pcap4j.core.Pcaps; +import org.pcap4j.packet.*; +import org.pcap4j.packet.namednumber.EtherType; +import org.pcap4j.packet.namednumber.IpNumber; +import org.pcap4j.packet.namednumber.IpVersion; +import org.pcap4j.packet.namednumber.TcpPort; +import org.pcap4j.packet.namednumber.tls.*; +import org.pcap4j.packet.tls.extensions.TlsExtension; +import org.pcap4j.packet.tls.extensions.UnimplementedTlsExtension; +import org.pcap4j.packet.tls.records.HandshakeRecord; +import org.pcap4j.packet.tls.records.handshakes.HandshakeRecordContent; +import org.pcap4j.packet.tls.records.handshakes.ServerHelloHandshakeRecordContent; +import org.pcap4j.util.MacAddress; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileInputStream; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Collections; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +public class TlsPacketTest extends AbstractPacketTest { + + private static final Logger logger = LoggerFactory.getLogger(TlsPacketTest.class); + + private final TlsPacket packet; + + public TlsPacketTest() { + TlsPacket.Builder b = new TlsPacket.Builder(); + byte[] random = new byte[32]; + byte[] sessionId = new byte[32]; + Arrays.fill(random, (byte) 0x11); + Arrays.fill(sessionId, (byte) 0x22); + + TlsExtension extension = new UnimplementedTlsExtension(ExtensionType.PADDING, + (short) 3, + new byte[] {0, 0, 0}); + + HandshakeRecordContent recordContent = new ServerHelloHandshakeRecordContent( + TlsVersion.TLS_1_0, + random, + sessionId, + (short) 7, + Collections.singletonList(extension), + CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, + CompressionMethod.NULL + ); + + HandshakeRecord record = new HandshakeRecord( + HandshakeType.SERVER_HELLO, + 79, + recordContent); + + b.contentType(ContentType.HANDSHAKE) + .version(TlsVersion.TLS_1_2) + .recordLength((short) 83) + .record(record); + + this.packet = b.build(); + } + + @Test + public void testNewPacket() { + try { + TlsPacket p = TlsPacket.newPacket(packet.getRawData(), 0, packet.getRawData().length); + assertEquals(packet, p); + } catch (IllegalRawDataException e) { + throw new AssertionError(e); + } + } + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + logger.info("########## " + TlsPacketTest.class.getSimpleName() + " START ##########"); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + logger.info("########## " + TlsPacketTest.class.getSimpleName() + " END ##########"); + } + + @Override + public void testDump() throws Exception { + String dumpFile = + new StringBuilder() + .append(tmpDirPath) + .append("/") + .append(getClass().getSimpleName()) + .append(".pcap") + .toString(); + Packet p = getWholePacket(); + + PcapHandle handle = Pcaps.openDead(getDataLinkType(), 65536); + PcapDumper dumper = handle.dumpOpen(dumpFile); + dumper.dump(p, new Timestamp(0)); + dumper.close(); + handle.close(); + + PcapHandle reader = Pcaps.openOffline(dumpFile); + assertEquals(p, prepareWholePacket(reader.getNextPacket())); + reader.close(); + + FileInputStream in1 = + new FileInputStream( + new StringBuilder() + .append(resourceDirPath) + .append("/") + .append(getClass().getSimpleName()) + .append(".pcap") + .toString()); + FileInputStream in2 = new FileInputStream(dumpFile); + + byte[] buffer1 = new byte[100]; + byte[] buffer2 = new byte[100]; + int size; + while ((size = in1.read(buffer1)) != -1) { + assertEquals(size, in2.read(buffer2)); + assertArrayEquals(buffer1, buffer2); + } + + in1.close(); + in2.close(); + } + + private Packet prepareWholePacket(Packet p) throws IllegalRawDataException { + TcpPacket tcpPacket = p.get(TcpPacket.class); + byte[] tcpData = tcpPacket.getPayload().getRawData(); + TlsPacket tlsPacket = TlsPacket.newPacket(tcpData, 0, tcpData.length); + TcpPacket.Builder newTcpPacketB = tcpPacket.getBuilder() + .payloadBuilder(tlsPacket.getBuilder()); + IpV4Packet.Builder newIpv4PacketB = p.get(IpV4Packet.class).getBuilder() + .payloadBuilder(newTcpPacketB); + return p.get(EthernetPacket.class).getBuilder() + .payloadBuilder(newIpv4PacketB) + .build(); + } + + @Override + protected Packet getPacket() throws Exception { + return packet; + } + + @Override + protected Packet getWholePacket() throws Exception { + Inet4Address srcAddr; + Inet4Address dstAddr; + try { + srcAddr = (Inet4Address) InetAddress.getByName("192.168.0.1"); + dstAddr = (Inet4Address) InetAddress.getByName("192.168.0.2"); + } catch (Exception e) { + throw new AssertionError("Never get here."); + } + + TcpPacket.Builder b = new TcpPacket.Builder(); + b.dstPort(TcpPort.HTTPS) + .srcPort(TcpPort.getInstance((short) 12345)) + .srcAddr(srcAddr) + .dstAddr(dstAddr) + .sequenceNumber(0) + .acknowledgmentNumber(0) + .dataOffset((byte) 0) + .reserved((byte) 0) + .urg(false) + .ack(false) + .psh(false) + .rst(false) + .syn(false) + .fin(false) + .window((short) 0) + .checksum((short) 0) + .urgentPointer((short) 0) + .options(Collections.emptyList()) + .correctChecksumAtBuild(true) + .correctLengthAtBuild(true) + .paddingAtBuild(true) + .payloadBuilder(packet.getBuilder()); + + IpV4Packet.Builder IpV4b = new IpV4Packet.Builder(); + IpV4b.version(IpVersion.IPV4) + .tos(IpV4Rfc1349Tos.newInstance((byte) 0)) + .identification((short) 100) + .ttl((byte) 100) + .protocol(IpNumber.TCP) + .srcAddr(srcAddr) + .dstAddr(dstAddr) + .payloadBuilder(b) + .correctChecksumAtBuild(true) + .correctLengthAtBuild(true) + .paddingAtBuild(true); + + EthernetPacket.Builder eb = new EthernetPacket.Builder(); + eb.dstAddr(MacAddress.getByName("fe:00:00:00:00:02")) + .srcAddr(MacAddress.getByName("fe:00:00:00:00:01")) + .type(EtherType.IPV4) + .payloadBuilder(IpV4b) + .paddingAtBuild(true); + + return eb.build(); + } +} diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.log b/pcap4j-packettest/src/test/resources/TlsPacketTest.log new file mode 100644 index 000000000..0d3402f57 --- /dev/null +++ b/pcap4j-packettest/src/test/resources/TlsPacketTest.log @@ -0,0 +1,11 @@ +[TLS Header (88 bytes)] + Version: 771 (TLS 1.2) + Type: 22 (Handshake) + Handshake length: 79 + Handshake type: 2 (Server Hello) + TLS version: 769 (TLS 1.0) + Random: 1111111111111111111111111111111111111111111111111111111111111111 + Session id: 2222222222222222222222222222222222222222222222222222222222222222 + Extensions: [padding [3 bytes]] + Cipher suite: 53 (TLS_RSA_WITH_AES_256_CBC_SHA) + Compression method: 0 (null) \ No newline at end of file diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.obj b/pcap4j-packettest/src/test/resources/TlsPacketTest.obj new file mode 100644 index 0000000000000000000000000000000000000000..826e84f247edfb30b6d19ce5cdb78559a587d54c GIT binary patch literal 4387 zcmeHKTWAzl82)!Rmujp@6fdm`r%~Iiw6mAECMK4etbwFmFU`aYED|TX$IR;N%sO+{ zZu%g!N{b58he`#d2rbx4pjZm2T6`)krJzO7(o%|8Dwa|UwYP^p^grj!&Q6l830U7; z26oPw^Iy;TzyCX9zd)^H!xGCLQ3@HYuzHVD&@y`|Qw9xZi+DTObt0U4y6*WP1XEC_ zQ!Ptv22Z3=BqBv3QY7MutiZQEv9K!z^#yIzu(T|LN2|z48(k$E$W$M?haF~X873E9 zYq|9Jr(;)IgHW4-hjq=-lU9}{wTw;~Eb;3uvYZh~X)lg$(~KfTALi<`q%u2aj)>*^ z-~iO5puwQ#2-E#jb8PK}4I0z@a}DUk1j$kXQ}&3@U2aeD?9E?(>|DpY`5!|NNI~s> z?gE2(sXf|$En;ZqNM!Ty9-3iYLQONDR`|5iZ!$VU?Rhs&zx~%suXY3>(C><4cA6^d zHWl;3)P7~`__BuAuOAHplnQ~{7e6dHJghnvsE@57(Khi!NdjNuBpT(<>fK^8Mq>B* ziAPC1et#bfr!C>e6>aA)F*(F|MX=GRn-GzfSpcxZohaH6O!ti4S@d_^Lxa~v{`l90 zp%ADz+8hcrPxB)!)BGR-P!9_rgo?d=xsV=AsYKQVY3=AB!=sEk;hnPy*+y+AXPKR( zy*)-+`LdW2595cy(E{z{nQZOT%&enpdnunL#2XTMh*5Oyqz_EWl2(=4`>BnV4a1Vs z+yYLyHrK2z+lonnq*{;&vmQilfA?xF4dgMCBYz3Narv1TaQlN?g}x@FW!D_^i( zXY-Wl7CIayt!B|M!X>QumA;CXh*ts03gR8y`Q}frjULVhp+-yM#`1Hv-LUw5M!C{?5; z8$?O>FmgFgIQi*MAzq5I8zU{+Ebf$9lE{c zkEKYgddkF#SHkRt)x+eWxqzy8Y9*{5fA7|j$1dOeCkUZ_Xw=KCxs3DmF3vOPt^&EJ z*8^%#)QLmLyjUjgP;ta zE*ZP)*rkuYUOc{g{H)lqhK%U9DsQ(lY-|+)46!*=>Af38>t&FbL72XlEyZ}#+A!lF z?-JhSJLe88yLs@NAk?YQL_NwOx3~uy9a%N~UUQ#aS;U}8(tUXm$vLbmjm=xID#poY z8fJO&{0Js0ZJG}k-sZi7E|&Z9u*ZDy+!3}so_MG!Ay>|=UVw#hcHQ1NQ$o<1VT-aJNEu> zJI-HS|2xMh9?(k0@2G-CqPE5gXsEhnGks(G{MEa@9l#{06Ho&d6uC6-qnze@12WC! zp}Dehnp;E*y7T1J?VB7NrrM=!`nKTJAHIC&Wq)LDlM@VSeJFq`t8Ct6m6AS-a$a}h ze8#$E#C$rJ-i=F3Ly$m2ZPWWcrGU*NOa5HWK1le?)o=zb)UE>5I)m-@5Q`rZLpwXZ d@XV=kpT;@<8 Date: Sun, 10 May 2020 17:31:06 +0300 Subject: [PATCH 08/10] Improve test coverage --- .../java/org/pcap4j/packet/TlsPacket.java | 11 ++++++++++ .../org/pcap4j/test/packet/TlsPacketTest.java | 19 +++++++++++++----- .../src/test/resources/TlsPacketTest.log | 6 +++++- .../src/test/resources/TlsPacketTest.obj | Bin 4387 -> 5112 bytes .../src/test/resources/TlsPacketTest.pcap | Bin 182 -> 192 bytes 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java index a71a22f82..a9c87ffb4 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java @@ -197,6 +197,17 @@ public Builder record(TlsRecord record) { return this; } + @Override + public TlsPacket.Builder payloadBuilder(Packet.Builder payloadBuilder) { + this.payloadBuilder = payloadBuilder; + return this; + } + + @Override + public Packet.Builder getPayloadBuilder() { + return payloadBuilder; + } + @Override public TlsPacket build() { return new TlsPacket(this); diff --git a/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java b/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java index c0399005c..9c1343c69 100644 --- a/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java +++ b/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java @@ -14,7 +14,9 @@ import org.pcap4j.packet.namednumber.tls.*; import org.pcap4j.packet.tls.extensions.TlsExtension; import org.pcap4j.packet.tls.extensions.UnimplementedTlsExtension; +import org.pcap4j.packet.tls.records.ApplicationDataRecord; import org.pcap4j.packet.tls.records.HandshakeRecord; +import org.pcap4j.packet.tls.records.TlsRecord; import org.pcap4j.packet.tls.records.handshakes.HandshakeRecordContent; import org.pcap4j.packet.tls.records.handshakes.ServerHelloHandshakeRecordContent; import org.pcap4j.util.MacAddress; @@ -46,9 +48,9 @@ public TlsPacketTest() { TlsExtension extension = new UnimplementedTlsExtension(ExtensionType.PADDING, (short) 3, - new byte[] {0, 0, 0}); + new byte[]{0, 0, 0}); - HandshakeRecordContent recordContent = new ServerHelloHandshakeRecordContent( + HandshakeRecordContent handshakeRecordContent = new ServerHelloHandshakeRecordContent( TlsVersion.TLS_1_0, random, sessionId, @@ -58,15 +60,22 @@ public TlsPacketTest() { CompressionMethod.NULL ); - HandshakeRecord record = new HandshakeRecord( + TlsRecord handshakeRecord = new HandshakeRecord( HandshakeType.SERVER_HELLO, 79, - recordContent); + handshakeRecordContent); + + TlsRecord dataRecord = new ApplicationDataRecord(new byte[]{1, 2, 3, 4, 5}); b.contentType(ContentType.HANDSHAKE) .version(TlsVersion.TLS_1_2) .recordLength((short) 83) - .record(record); + .record(handshakeRecord) + .payloadBuilder(new TlsPacket.Builder() + .version(TlsVersion.TLS_1_2) + .contentType(ContentType.APPLICATION_DATA) + .recordLength((short) 5) + .record(dataRecord)); this.packet = b.build(); } diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.log b/pcap4j-packettest/src/test/resources/TlsPacketTest.log index 0d3402f57..e6a58cb16 100644 --- a/pcap4j-packettest/src/test/resources/TlsPacketTest.log +++ b/pcap4j-packettest/src/test/resources/TlsPacketTest.log @@ -8,4 +8,8 @@ Session id: 2222222222222222222222222222222222222222222222222222222222222222 Extensions: [padding [3 bytes]] Cipher suite: 53 (TLS_RSA_WITH_AES_256_CBC_SHA) - Compression method: 0 (null) \ No newline at end of file + Compression method: 0 (null) +[TLS Header (10 bytes)] + Version: 771 (TLS 1.2) + Type: 23 (Application Data) + Encrypted data: [5 bytes] \ No newline at end of file diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.obj b/pcap4j-packettest/src/test/resources/TlsPacketTest.obj index 826e84f247edfb30b6d19ce5cdb78559a587d54c..a4a0c5636e62ef8fc3c69d329d09fd07cea69d3e 100644 GIT binary patch delta 821 zcmZ3i^h15aaYnua`2tTXiVGR)7}!b}RX5*eV`tP?Ff>;%Fa{$71p`wB149J^BQVzl z$c3r~>)~WzU`U$$mPwW|Y4U&e2oZ5+W(HP9CT12^n3+s!n-e*9GYW7;hxi05c%&w# zq!uY?7#d72;Lrxzq2X9ikdv95Sdy8ar{I!UlBmh0px~O9TvS<5lA5BB0u-@Qh&EM7 zsw_z@j@_)mdXQ=IVKT9?={Wg4zcUL^RA%x$P8lAE7=vkX5rgsMcrLlg2l!bgHwY;5168o(mFDDt6=*X| zKFFsw`I>-iJy4t{IJKw@=x~qJoSb}!JQJ95gWF{UF_)PcOf!HN$`~VpiQi~KkQgd?h RA&Qv5lq=i;w{ND&AG W0P%^r6Jw&d#F?2HSQ(j^Sy%zs&JXec delta 70 zcmX@WxQ%gwf=wR-0|N;E17ZdyFv-Zl;L5vbgkivH5z=0JEj6lp}V9B@}qzD88 LfcWj^i7` Date: Sun, 10 May 2020 18:05:07 +0300 Subject: [PATCH 09/10] Improve test coverage, new constructors --- .../keyshare/ClientKeyShareExtension.java | 7 +++++++ .../extensions/keyshare/KeyShareEntry.java | 9 ++++++++- .../keyshare/KeyShareExtension.java | 3 ++- .../keyshare/ServerKeyShareExtension.java | 6 ++++++ .../org/pcap4j/test/packet/TlsPacketTest.java | 19 +++++++++++++----- .../src/test/resources/TlsPacketTest.log | 6 +++--- .../src/test/resources/TlsPacketTest.obj | Bin 5112 -> 5852 bytes .../src/test/resources/TlsPacketTest.pcap | Bin 192 -> 204 bytes 8 files changed, 40 insertions(+), 10 deletions(-) diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java index adb13d5bc..0c9907c76 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java @@ -4,6 +4,7 @@ import org.pcap4j.util.ByteArrays; import java.util.Arrays; +import java.util.List; import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; @@ -22,6 +23,12 @@ public ClientKeyShareExtension(ExtensionType type, byte[] rawData, int offset, s readEntries(rawData, KEY_SHARE_ENTRY_OFFSET + offset, offset + keyShareLength); } + public ClientKeyShareExtension(ExtensionType type, short extensionLength, short keyShareLength, List entries) { + super(type, extensionLength); + this.keyShareLength = keyShareLength; + this.entries = entries; + } + @Override public byte[] toByteArray() { return ByteArrays.concatenate(Arrays.asList( diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java index 8f503231c..1fe28b1c2 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java @@ -3,11 +3,12 @@ import org.pcap4j.util.ByteArrays; import org.pcap4j.packet.namednumber.tls.KeyGroup; +import java.io.Serializable; import java.util.Arrays; import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; -public class KeyShareEntry { +public class KeyShareEntry implements Serializable { private static final int GROUP_OFFSET = 0; private static final int KEY_EXHANGE_LENGTH_OFFSET = GROUP_OFFSET + SHORT_SIZE_IN_BYTES; @@ -24,6 +25,12 @@ public KeyShareEntry(byte[] rawData, int offset) { System.arraycopy(rawData, KEY_EXCHANGE_OFFSET + offset, keyExchange, 0, keyExhangeLength); } + public KeyShareEntry(KeyGroup group, short keyExhangeLength, byte[] keyExchange) { + this.group = group; + this.keyExhangeLength = keyExhangeLength; + this.keyExchange = keyExchange; + } + public int size() { return SHORT_SIZE_IN_BYTES + SHORT_SIZE_IN_BYTES + keyExhangeLength; } diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java index a8f00afd1..460a4ad73 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java @@ -9,7 +9,7 @@ public abstract class KeyShareExtension extends TlsExtension { - private final List entries = new ArrayList(); + protected List entries; public static KeyShareExtension newInstance(ExtensionType type, byte[] rawData, int offset, short extensionLength, boolean client) { @@ -24,6 +24,7 @@ public static KeyShareExtension newInstance(ExtensionType type, byte[] rawData, protected KeyShareExtension(ExtensionType type, short extensionLength) { super(type, extensionLength); + this.entries = new ArrayList(); } protected void readEntries(byte[] rawData, int cursor, int end) { diff --git a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java index 9a69eaa36..8ebb35bf4 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java @@ -4,6 +4,7 @@ import org.pcap4j.util.ByteArrays; import java.util.Arrays; +import java.util.List; public class ServerKeyShareExtension extends KeyShareExtension { @@ -14,6 +15,11 @@ public ServerKeyShareExtension(ExtensionType type, byte[] rawData, int offset, s readEntry(rawData, KEY_SHARE_ENTRY_OFFSET + offset); } + public ServerKeyShareExtension(ExtensionType type, short extensionLength, List entries) { + super(type, extensionLength); + this.entries = entries; + } + @Override public byte[] toByteArray() { return ByteArrays.concatenate(Arrays.asList( diff --git a/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java b/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java index 9c1343c69..adee17393 100644 --- a/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java +++ b/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java @@ -14,6 +14,8 @@ import org.pcap4j.packet.namednumber.tls.*; import org.pcap4j.packet.tls.extensions.TlsExtension; import org.pcap4j.packet.tls.extensions.UnimplementedTlsExtension; +import org.pcap4j.packet.tls.extensions.keyshare.KeyShareEntry; +import org.pcap4j.packet.tls.extensions.keyshare.ServerKeyShareExtension; import org.pcap4j.packet.tls.records.ApplicationDataRecord; import org.pcap4j.packet.tls.records.HandshakeRecord; import org.pcap4j.packet.tls.records.TlsRecord; @@ -46,30 +48,37 @@ public TlsPacketTest() { Arrays.fill(random, (byte) 0x11); Arrays.fill(sessionId, (byte) 0x22); - TlsExtension extension = new UnimplementedTlsExtension(ExtensionType.PADDING, + TlsExtension paddingExtension = new UnimplementedTlsExtension( + ExtensionType.PADDING, (short) 3, new byte[]{0, 0, 0}); + TlsExtension keyShareExtension = new ServerKeyShareExtension( + ExtensionType.KEY_SHARE, + (short) 8, + Collections.singletonList(new KeyShareEntry(KeyGroup.X25519, (short) 4, new byte[]{1, 2, 3, 4})) + ); + HandshakeRecordContent handshakeRecordContent = new ServerHelloHandshakeRecordContent( TlsVersion.TLS_1_0, random, sessionId, - (short) 7, - Collections.singletonList(extension), + (short) 19, + Arrays.asList(keyShareExtension, paddingExtension), CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, CompressionMethod.NULL ); TlsRecord handshakeRecord = new HandshakeRecord( HandshakeType.SERVER_HELLO, - 79, + 91, handshakeRecordContent); TlsRecord dataRecord = new ApplicationDataRecord(new byte[]{1, 2, 3, 4, 5}); b.contentType(ContentType.HANDSHAKE) .version(TlsVersion.TLS_1_2) - .recordLength((short) 83) + .recordLength((short) 95) .record(handshakeRecord) .payloadBuilder(new TlsPacket.Builder() .version(TlsVersion.TLS_1_2) diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.log b/pcap4j-packettest/src/test/resources/TlsPacketTest.log index e6a58cb16..ae4706189 100644 --- a/pcap4j-packettest/src/test/resources/TlsPacketTest.log +++ b/pcap4j-packettest/src/test/resources/TlsPacketTest.log @@ -1,12 +1,12 @@ -[TLS Header (88 bytes)] +[TLS Header (100 bytes)] Version: 771 (TLS 1.2) Type: 22 (Handshake) - Handshake length: 79 + Handshake length: 91 Handshake type: 2 (Server Hello) TLS version: 769 (TLS 1.0) Random: 1111111111111111111111111111111111111111111111111111111111111111 Session id: 2222222222222222222222222222222222222222222222222222222222222222 - Extensions: [padding [3 bytes]] + Extensions: [key_share [x25519], padding [3 bytes]] Cipher suite: 53 (TLS_RSA_WITH_AES_256_CBC_SHA) Compression method: 0 (null) [TLS Header (10 bytes)] diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.obj b/pcap4j-packettest/src/test/resources/TlsPacketTest.obj index a4a0c5636e62ef8fc3c69d329d09fd07cea69d3e..ff48bea0cabc0da4413fac2cc2f0e05979fd3aca 100644 GIT binary patch delta 960 zcmb`GPiWI{6vy8$S-Y;){&8!;NhRu>Ro5O~J9FlOCK1o&>!Vhk`Jef)~-#JP3O5;P02t!q`oOA4z_^&-?Rz@8#E# zjrhuI6gwJRTei&`a0}cPIw$mSe9AdICtlAmx6;M*uZ ztZk{fsm15gR@`=tX%PJzalJOOv2k)h$C)owXBfyy)ADzxWNt zW8xKe7|#ZHZwrZ3A39zR#8C>T{b$e#nqzQh4ic5jcV*&zH6B*p|L895kS85pK9q%bg~uw7YoUoz+SV4SN0Lmg3(*OVf delta 108 zcmX@Zcz|(&g69kd1_luR2gD3aV3Lu8!Igobiy?)9A%*SAwgW2|7=f6{z>;w{ND&AG w0P%^r3=Cq-%nZRy3=ICvj1vnbCN^+P>{JzEXAosz1}YE-O0qICF|)7&0L;%5D*ylh From 1b6c01f17fc662a35f992c7c7fda9f37305a85e1 Mon Sep 17 00:00:00 2001 From: serega6531 Date: Sun, 10 May 2020 18:18:13 +0300 Subject: [PATCH 10/10] Improve test coverage --- .../org/pcap4j/test/packet/TlsPacketTest.java | 10 +++++++++- .../src/test/resources/TlsPacketTest.log | 6 +++++- .../src/test/resources/TlsPacketTest.obj | Bin 5852 -> 6994 bytes .../src/test/resources/TlsPacketTest.pcap | Bin 204 -> 211 bytes 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java b/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java index adee17393..c93f17d02 100644 --- a/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java +++ b/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java @@ -16,6 +16,7 @@ import org.pcap4j.packet.tls.extensions.UnimplementedTlsExtension; import org.pcap4j.packet.tls.extensions.keyshare.KeyShareEntry; import org.pcap4j.packet.tls.extensions.keyshare.ServerKeyShareExtension; +import org.pcap4j.packet.tls.records.AlertRecord; import org.pcap4j.packet.tls.records.ApplicationDataRecord; import org.pcap4j.packet.tls.records.HandshakeRecord; import org.pcap4j.packet.tls.records.TlsRecord; @@ -76,6 +77,8 @@ public TlsPacketTest() { TlsRecord dataRecord = new ApplicationDataRecord(new byte[]{1, 2, 3, 4, 5}); + TlsRecord alertRecord = new AlertRecord(AlertLevel.WARNING, AlertDescription.unknown_ca); + b.contentType(ContentType.HANDSHAKE) .version(TlsVersion.TLS_1_2) .recordLength((short) 95) @@ -84,7 +87,12 @@ public TlsPacketTest() { .version(TlsVersion.TLS_1_2) .contentType(ContentType.APPLICATION_DATA) .recordLength((short) 5) - .record(dataRecord)); + .record(dataRecord) + .payloadBuilder(new TlsPacket.Builder() + .version(TlsVersion.TLS_1_2) + .contentType(ContentType.ALERT) + .recordLength((short) 2) + .record(alertRecord))); this.packet = b.build(); } diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.log b/pcap4j-packettest/src/test/resources/TlsPacketTest.log index ae4706189..d7991c62e 100644 --- a/pcap4j-packettest/src/test/resources/TlsPacketTest.log +++ b/pcap4j-packettest/src/test/resources/TlsPacketTest.log @@ -12,4 +12,8 @@ [TLS Header (10 bytes)] Version: 771 (TLS 1.2) Type: 23 (Application Data) - Encrypted data: [5 bytes] \ No newline at end of file + Encrypted data: [5 bytes] +[TLS Header (7 bytes)] + Version: 771 (TLS 1.2) + Type: 21 (Alert) + Alert [level: warning, description: unknown_ca] \ No newline at end of file diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.obj b/pcap4j-packettest/src/test/resources/TlsPacketTest.obj index ff48bea0cabc0da4413fac2cc2f0e05979fd3aca..206de602fdfb9bba27488d18b9bb41b94a773650 100644 GIT binary patch delta 1034 zcmcbkd&z9WaYnw93vYZYiVGR)7}!b}<2GMq^kh_1Ff>&#Fa{$71p^}m149L41E?af zQcea2hSJIU%(9H7lQ>hP#hIBISQ(j^Sy)AZEG9;n+7hM>oAWp?FixJzn$6D@9pV$L z;E|e`l3JvoVLn+wRNKl>LBla8wWvgsOF;q5P>9Y+ElbU@QYcR>%FE14*HK7GElw`V zEGWs$&$Ch}&CAZqFVBllPTc&Tbt50&1vinuFvl|(O=e`44I;|zf>2GRAb$%2JtK(I z3k>%s3yNk@+4YmFMBOGo5}7qQRIIHY9HI=6D1e0S5uV2-aBqna6B+F29%4s}35F8X z;8#ehEJ-cajO9|8tR<>gPkuziLTnaAb^pUuqTCM({yv~eT~P9aM+PCcgOW}-B`#)Q z0=rhVgn<>D>cBj0(c&To&B;1Ea%Nz`pw#62qLeOu)0`bS`Hz?wn4=lklk@XRQu9hc z&NlO5;6_TDB@8B$_wg#rfVH|H(yX-)11mU5moVso6v%=V_<$0*bwvT(%fLJXwB2ZO zp|FxAx)GbXTLg;wm8LT>FjRnSRx4rPLSzJp+d;Z@K)Q_(<{MTAghb_BtwGYq4$W2& KO^hJZG7A8)IwXSt delta 138 zcmca)c1L%^aYjB(feXtkiVGR)7}!b}JvU!v^kkfTTTDPc4=Pw%#K08owC1z;4>pdF z2TTkM6$K0o40)3$a;AugGcz-=GBPossI20 diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.pcap b/pcap4j-packettest/src/test/resources/TlsPacketTest.pcap index be0817bf23021009a0bb0b17cb5a4aaa67b587cd..843ec8d1bff1226db423398002e5b302d433e982 100644 GIT binary patch delta 78 zcmX@Zc$sm6g3W3M1_luR2gD3aV3Lu8!IgnwE<*|fLkioK#Rpa}Faj}?fhFT^kRlKW T0OB8w6JrY4MVXlym>3NJ!Wj^S delta 70 zcmcc2c!qI;g3S^J1_luR2gD3aV3Lu8!Ignw8bb;LLkioKRR>luFaj}?fhFT^kRlKW L0Ai=!i7^ELIF}E2