
enum {
       client_hello(1),
       server_hello(2),
       new_session_ticket(4),
       hello_retry_request(6),
       encrypted_extensions(8),
       certificate(11),
       certificate_request(13),
       certificate_verify(15),
       finished(20),
       key_update(24),
       (255)
   } HandshakeType;

struct {
       HandshakeType msg_type;
       uint24 length;
       select (HandshakeType) {
           case client_hello:          ClientHello;
           case server_hello:          ServerHello;
           case hello_retry_request:   HelloRetryRequest;
           case encrypted_extensions:  EncryptedExtensions;
           case certificate_request:   CertificateRequest;
           case certificate:           Certificate;
           case certificate_verify:    CertificateVerify;
           case finished:              Finished;
           case new_session_ticket:    NewSessionTicket;
           case key_update:            KeyUpdate;
       } body;
   } Handshake;

struct {
       uint8 major;
       uint8 minor;
   } ProtocolVersion;

struct {
  uint8 cs[2];
} CipherSuite;

struct {
       opaque random_bytes[32];
   } Random;

enum {
       supported_groups(10),
       signature_algorithms(13),
       key_share(40),
       pre_shared_key(41),
       early_data(42),
       cookie(44),
       (65535)
   } ExtensionType;

struct {
       ExtensionType extension_type;
       opaque extension_data<0..2^16-1>;
   } Extension;

struct {
       ProtocolVersion client_version = { 3, 4 };    /* TLS v1.3 */
       Random random;
       opaque legacy_session_id<0..32>;
       CipherSuite cipher_suites<2..2^16-2>;
       opaque legacy_compression_methods<1..2^8-1>;
       Extension extensions<0..2^16-1>;
   } ClientHello;

struct {
       ProtocolVersion server_version;
       Random random;
       CipherSuite cipher_suite;
       Extension extensions<0..2^16-1>;
   } ServerHello;

enum {
       /* Elliptic Curve Groups (ECDHE) */
       secp256r1 (23), secp384r1 (24), secp521r1 (25),
       x25519 (29), x448 (30),

       /* Finite Field Groups (DHE) */
       ffdhe2048 (256), ffdhe3072 (257), ffdhe4096 (258),
       ffdhe6144 (259), ffdhe8192 (260),

       /* Reserved Code Points */
       ffdhe_private_use (0x01FC..0x01FF),
       ecdhe_private_use (0xFE00..0xFEFF),
       (0xFFFF)
   } NamedGroup;

struct {
       NamedGroup named_group_list<2..2^16-1>;
   } NamedGroupList;

struct {
       ProtocolVersion server_version;
       CipherSuite cipher_suite;
       NamedGroup selected_group;
       Extension extensions<0..2^16-1>;
   } HelloRetryRequest;

struct {
       opaque cookie<0..2^16-1>;
   } Cookie;

enum {
       /* RSASSA-PKCS1-v1_5 algorithms */
       rsa_pkcs1_sha1 (0x0201),
       rsa_pkcs1_sha256 (0x0401),
       rsa_pkcs1_sha384 (0x0501),
       rsa_pkcs1_sha512 (0x0601),

       /* ECDSA algorithms */
       ecdsa_secp256r1_sha256 (0x0403),
       ecdsa_secp384r1_sha384 (0x0503),
       ecdsa_secp521r1_sha512 (0x0603),

       /* RSASSA-PSS algorithms */
       rsa_pss_sha256 (0x0700),
       rsa_pss_sha384 (0x0701),
       rsa_pss_sha512 (0x0702),

       /* EdDSA algorithms */
       ed25519 (0x0703),
       ed448 (0x0704),

       /* Reserved Code Points */
       private_use (0xFE00..0xFFFF),
       (0xFFFF)
   } SignatureScheme;

struct {
       NamedGroup group;
       opaque key_exchange<1..2^16-1>;
   } KeyShareEntry;

struct {
       select (role) {
           case client:
               KeyShareEntry client_shares<0..2^16-1>;

           case server:
               KeyShareEntry server_share;
       }
   } KeyShare;

struct {
       select (Role) {
           case client:
               psk_identity identities<2..2^16-1>;

           case server:
               uint16 selected_identity;
       }
   } PreSharedKeyExtension;

struct {
       select (Role) {
           case client:
               uint32 obfuscated_ticket_age;

           case server:
/*ADL              struct {};*/
       }
   } EarlyDataIndication;

struct {
       Extension extensions<0..2^16-1>;
   } EncryptedExtensions;

struct {
       opaque certificate_extension_oid<1..2^8-1>;
       opaque certificate_extension_values<0..2^16-1>;
   } CertificateExtension;

struct {
  opaque dn<1..2^16-1>;
} DistinguishedName;

struct {
       opaque certificate_request_context<0..2^8-1>;
       SignatureScheme
         supported_signature_algorithms<2..2^16-2>;
       DistinguishedName certificate_authorities<0..2^16-1>;
       CertificateExtension certificate_extensions<0..2^16-1>;
   } CertificateRequest;

struct {
  opaque asn1<1..2^24-1>;
} ASN1Cert;

struct {
       opaque certificate_request_context<0..2^8-1>;
       ASN1Cert certificate_list<0..2^24-1>;
   } Certificate;

struct {
        SignatureScheme algorithm;
        opaque signature<0..2^16-1>;
   } CertificateVerify;

struct {
       opaque verify_data[Hash.length];
   } Finished;

enum {
	test(1),
	(65535)
} TicketExtensionType;

struct {
     TicketExtensionType extension_type;
     opaque extension_data<1..2^16-1>;
 } TicketExtension;

enum {
   allow_early_data(1),
   allow_dhe_resumption(2),
   allow_psk_resumption(4),
   (4294967295)
 } TicketFlags;

struct {
     uint32 ticket_lifetime;
     uint32 flags;
     uint32 ticket_age_add;
     TicketExtension extensions<0..2^16-2>;
     opaque ticket<1..2^16-1>;
 } NewSessionTicket;

/*struct {} KeyUpdate;*/

enum {
       alert(21),
       handshake(22),
       application_data(23),
       (255)
   } ContentType;

struct {
       ContentType content_type;
       ProtocolVersion record_version = { 3, 1 };    /* TLS v1.x */
       opaque fragment<0..2^16-1>;
/*
       uint16 length;
       opaque fragment[TLSPlaintext.length];
*/
   } TLSPlaintext;

/*
struct {
      opaque content[TLSPlaintext.length];
      ContentType content_type;
      uint8 zeros[length_of_padding];
   } TLSInnerPlaintext;
*/

struct {
       ContentType opaque_type = application_data(23); /* see fragment.type */
       ProtocolVersion record_version = { 3, 1 };    /* TLS v1.x */
/*       uint16 length; */
       opaque encrypted_record<0..2^16-1>;
/*       opaque encrypted_record[length]; */
   } TLSCiphertext;

enum { warning(1), fatal(2), (255) } AlertLevel;

enum {
       close_notify(0),
       end_of_early_data(1),
       unexpected_message(10),
       bad_record_mac(20),
       record_overflow(22),
       handshake_failure(40),
       bad_certificate(42),
       unsupported_certificate(43),
       certificate_revoked(44),
       certificate_expired(45),
       certificate_unknown(46),
       illegal_parameter(47),
       unknown_ca(48),
       access_denied(49),
       decode_error(50),
       decrypt_error(51),
       protocol_version(70),
       insufficient_security(71),
       internal_error(80),
       inappropriate_fallback(86),
       user_canceled(90),
       missing_extension(109),
       unsupported_extension(110),
       certificate_unobtainable(111),
       unrecognized_name(112),
       bad_certificate_status_response(113),
       bad_certificate_hash_value(114),
       unknown_psk_identity(115),
       (255)
   } AlertDescription;

struct {
       AlertLevel level;
       AlertDescription description;
   } Alert;

