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 new file mode 100644 index 000000000..a9c87ffb4 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/TlsPacket.java @@ -0,0 +1,216 @@ +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 final ContentType contentType; + private final TlsVersion version; + private final short recordLength; + private final TlsRecord record; + + private TlsHeader(Builder builder) { + this.contentType = builder.contentType; + this.version = builder.version; + this.recordLength = builder.recordLength; + this.record = builder.record; + } + + 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)); + 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 short getRecordLength() { + return recordLength; + } + + 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)); + rawFields.add(record.toByteArray()); + return rawFields; + } + + @Override + protected int calcLength() { + 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 ContentType contentType; + private TlsVersion version; + private short recordLength; + private TlsRecord record; + + private Packet.Builder payloadBuilder; + + 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 + 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-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..de6b6a645 --- /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..505cb731d --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/AlertLevel.java @@ -0,0 +1,36 @@ +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 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 { + return ENCRYPTED_ALERT; + } + } + + @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..29b7c5eca --- /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..a008312bd --- /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..ff70bd700 --- /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..eff32c6f8 --- /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..1c69fbe0d --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/namednumber/tls/HandshakeType.java @@ -0,0 +1,56 @@ +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) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + return 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..046375b19 --- /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..232be24c7 --- /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..5b3a5d9b1 --- /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..6c3855cf8 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/TlsExtension.java @@ -0,0 +1,54 @@ +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; + +import java.io.Serializable; + +public abstract class TlsExtension implements Serializable { + + /* + 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(); + } + + 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 new file mode 100644 index 000000000..32e963bd3 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/UnimplementedTlsExtension.java @@ -0,0 +1,41 @@ +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 { + + 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); + } + + public UnimplementedTlsExtension(ExtensionType type, short extensionLength, byte[] data) { + super(type, extensionLength); + this.data = data; + } + + @Override + public String toString() { + if(extensionLength > 0) { + return type.name() + " [" + extensionLength + " bytes]"; + } else { + 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 new file mode 100644 index 000000000..0c9907c76 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ClientKeyShareExtension.java @@ -0,0 +1,40 @@ +package org.pcap4j.packet.tls.extensions.keyshare; + +import org.pcap4j.packet.namednumber.tls.ExtensionType; +import org.pcap4j.util.ByteArrays; + +import java.util.Arrays; +import java.util.List; + +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); + int cursor = KEY_SHARE_ENTRY_OFFSET + offset; + ByteArrays.validateBounds(rawData, cursor, keyShareLength); + 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( + 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 new file mode 100644 index 000000000..1fe28b1c2 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareEntry.java @@ -0,0 +1,51 @@ +package org.pcap4j.packet.tls.extensions.keyshare; + +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 implements Serializable { + + 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 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; + } + + @Override + 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 new file mode 100644 index 000000000..460a4ad73 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/KeyShareExtension.java @@ -0,0 +1,58 @@ +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 { + + protected List entries; + + 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); + this.entries = new ArrayList(); + } + + 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(); + } + + 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 new file mode 100644 index 000000000..8ebb35bf4 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/extensions/keyshare/ServerKeyShareExtension.java @@ -0,0 +1,30 @@ +package org.pcap4j.packet.tls.extensions.keyshare; + +import org.pcap4j.packet.namednumber.tls.ExtensionType; +import org.pcap4j.util.ByteArrays; + +import java.util.Arrays; +import java.util.List; + +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); + } + + public ServerKeyShareExtension(ExtensionType type, short extensionLength, List entries) { + super(type, extensionLength); + this.entries = entries; + } + + @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/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..ab6bbb4f5 --- /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..1429d0b0f --- /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..22b625c05 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/AlertRecord.java @@ -0,0 +1,69 @@ +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 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, length); + } + + public AlertRecord(byte[] rawData, int offset, int length) { + this.content = ByteArrays.getSubArray(rawData, offset, length); + this.level = AlertLevel.getInstance(ByteArrays.getByte(rawData, LEVEL_OFFSET + offset)); + + if (level != AlertLevel.ENCRYPTED_ALERT) { + this.description = AlertDescription.getInstance(ByteArrays.getByte(rawData, DESCRIPTION_OFFSET + offset)); + } + } + + /** + * 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; + } + + @Override + public String toString() { + if (level != AlertLevel.ENCRYPTED_ALERT) { + return " Alert [level: " + level.name() + ", description: " + description.name() + "]"; + } else { + return " Encrypted Alert [" + content.length + " bytes]"; + } + } +} 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..50bb45782 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ApplicationDataRecord.java @@ -0,0 +1,41 @@ +package org.pcap4j.packet.tls.records; + +import org.pcap4j.util.ByteArrays; + +public class ApplicationDataRecord implements TlsRecord { + + /** + * 0x0 - Encrypted Application Data + * 0x0 + length - End + */ + + private final 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 ApplicationDataRecord(byte[] data) { + this.data = data; + } + + public byte[] getData() { + return data; + } + + @Override + 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 new file mode 100644 index 000000000..ccc6dd6c1 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/ChangeCipherSpecRecord.java @@ -0,0 +1,40 @@ +package org.pcap4j.packet.tls.records; + +import org.pcap4j.util.ByteArrays; + +public class ChangeCipherSpecRecord implements TlsRecord { + + /** + 0x0 - Change Cipher Spec Message + 0x1 - End + */ + + private final 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); + } + + public ChangeCipherSpecRecord(byte changeCipherSpecMessage) { + this.changeCipherSpecMessage = changeCipherSpecMessage; + } + + public byte getChangeCipherSpecMessage() { + return changeCipherSpecMessage; + } + + @Override + 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 new file mode 100644 index 000000000..e2c837d06 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HandshakeRecord.java @@ -0,0 +1,93 @@ +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 java.util.Arrays; + +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 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); + 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 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; + } + + @Override + public String toString() { + return " Handshake length: " + handshakeLength + "\n" + + " Handshake type: " + handshakeType + "\n" + + content.toString(); + } + + @Override + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + ByteArrays.toByteArray(handshakeType.value()), + ByteArrays.threeBytesIntToByteArray(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 new file mode 100644 index 000000000..8b66ef9d3 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/HeartbeatRecord.java @@ -0,0 +1,79 @@ +package org.pcap4j.packet.tls.records; + +import org.pcap4j.packet.namednumber.tls.HeartbeatMessageType; +import org.pcap4j.util.ByteArrays; + +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 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; + + 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); + } + + 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; + } + + 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]"; + } + + @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 new file mode 100644 index 000000000..2ebda9601 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/TlsRecord.java @@ -0,0 +1,9 @@ +package org.pcap4j.packet.tls.records; + +import java.io.Serializable; + +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 new file mode 100644 index 000000000..99dd9e183 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/BasicHandshakeRecordContent.java @@ -0,0 +1,45 @@ +package org.pcap4j.packet.tls.records.handshakes; + +import org.pcap4j.util.ByteArrays; + +public class BasicHandshakeRecordContent implements HandshakeRecordContent { + + /** + * 0x0 - Content + * 0x0 + length - End + */ + + private final 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 BasicHandshakeRecordContent(byte[] content) { + this.content = content; + } + + public byte[] getContent() { + return content; + } + + @Override + 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 new file mode 100644 index 000000000..1df71f68d --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/CertificateHandshakeRecordContent.java @@ -0,0 +1,90 @@ +package org.pcap4j.packet.tls.records.handshakes; + +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; + + private final int certificatesLength; + private final List rawCertificates; + + 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); + this.rawCertificates = new ArrayList(); + + 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 CertificateHandshakeRecordContent(int certificatesLength, List rawCertificates) { + this.certificatesLength = certificatesLength; + this.rawCertificates = rawCertificates; + } + + public int getCertificatesLength() { + return certificatesLength; + } + + 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(); + } + + @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 new file mode 100644 index 000000000..73d18aea7 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ClientHelloHandshakeRecordContent.java @@ -0,0 +1,146 @@ +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.ArrayList; +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; + +public class ClientHelloHandshakeRecordContent extends HelloHandshakeRecordContent { + + /* + 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 + 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 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); + 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); + } + + 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" + + " 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 new file mode 100644 index 000000000..8ea540992 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HandshakeRecordContent.java @@ -0,0 +1,9 @@ +package org.pcap4j.packet.tls.records.handshakes; + +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/HelloHandshakeRecordContent.java b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java new file mode 100644 index 000000000..5ff48965a --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/HelloHandshakeRecordContent.java @@ -0,0 +1,119 @@ +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.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; + +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 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); + 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 short getExtensionsLength() { + return extensionsLength; + } + + 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(); + } + + 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 new file mode 100644 index 000000000..d7fa1f38d --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/packet/tls/records/handshakes/ServerHelloHandshakeRecordContent.java @@ -0,0 +1,87 @@ +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; + +public class ServerHelloHandshakeRecordContent extends HelloHandshakeRecordContent { + + /* + 0x0 - TLS version + 0x2 - Server random + 0x22 - Session id length (sidl) + 0x23 - Session id + 0x23+sidl - 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 + 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 final CipherSuite cipherSuite; + private final 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 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; + } + + public CompressionMethod getCompressionMethod() { + return compressionMethod; + } + + @Override + public String toString() { + return super.toString() + "\n" + + " Cipher suite: " + cipherSuite.toString() + "\n" + + " Compression method: " + compressionMethod.toString(); + } + + @Override + public byte[] toByteArray() { + return ByteArrays.concatenate(Arrays.asList( + commonPartToByteArray(), + ByteArrays.toByteArray(cipherSuite.value()), + ByteArrays.toByteArray(compressionMethod.value()), + 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 793d2db91..972842ac5 100644 --- a/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java +++ b/pcap4j-core/src/main/java/org/pcap4j/util/ByteArrays.java @@ -404,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/util/DhClientParams.java b/pcap4j-core/src/main/java/org/pcap4j/util/DhClientParams.java new file mode 100644 index 000000000..422fe1d3d --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/util/DhClientParams.java @@ -0,0 +1,42 @@ +package org.pcap4j.util; + +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/util/EcdheServerParams.java b/pcap4j-core/src/main/java/org/pcap4j/util/EcdheServerParams.java new file mode 100644 index 000000000..c89c321ed --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/util/EcdheServerParams.java @@ -0,0 +1,44 @@ +package org.pcap4j.util; + +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/util/TlsKeyUtils.java b/pcap4j-core/src/main/java/org/pcap4j/util/TlsKeyUtils.java new file mode 100644 index 000000000..73ee1c712 --- /dev/null +++ b/pcap4j-core/src/main/java/org/pcap4j/util/TlsKeyUtils.java @@ -0,0 +1,112 @@ +package org.pcap4j.util; + +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 + + private TlsKeyUtils() { + } + + 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-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..c93f17d02 --- /dev/null +++ b/pcap4j-packettest/src/test/java/org/pcap4j/test/packet/TlsPacketTest.java @@ -0,0 +1,238 @@ +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.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; +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 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) 19, + Arrays.asList(keyShareExtension, paddingExtension), + CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, + CompressionMethod.NULL + ); + + TlsRecord handshakeRecord = new HandshakeRecord( + HandshakeType.SERVER_HELLO, + 91, + handshakeRecordContent); + + 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) + .record(handshakeRecord) + .payloadBuilder(new TlsPacket.Builder() + .version(TlsVersion.TLS_1_2) + .contentType(ContentType.APPLICATION_DATA) + .recordLength((short) 5) + .record(dataRecord) + .payloadBuilder(new TlsPacket.Builder() + .version(TlsVersion.TLS_1_2) + .contentType(ContentType.ALERT) + .recordLength((short) 2) + .record(alertRecord))); + + 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..d7991c62e --- /dev/null +++ b/pcap4j-packettest/src/test/resources/TlsPacketTest.log @@ -0,0 +1,19 @@ +[TLS Header (100 bytes)] + Version: 771 (TLS 1.2) + Type: 22 (Handshake) + Handshake length: 91 + Handshake type: 2 (Server Hello) + TLS version: 769 (TLS 1.0) + Random: 1111111111111111111111111111111111111111111111111111111111111111 + Session id: 2222222222222222222222222222222222222222222222222222222222222222 + 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)] + Version: 771 (TLS 1.2) + Type: 23 (Application Data) + 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 new file mode 100644 index 000000000..206de602f Binary files /dev/null and b/pcap4j-packettest/src/test/resources/TlsPacketTest.obj differ diff --git a/pcap4j-packettest/src/test/resources/TlsPacketTest.pcap b/pcap4j-packettest/src/test/resources/TlsPacketTest.pcap new file mode 100644 index 000000000..843ec8d1b Binary files /dev/null and b/pcap4j-packettest/src/test/resources/TlsPacketTest.pcap differ