
enum { server, client } ConnectionEnd;

enum { null, rc4, rc2, des, des3, des40, idea, aes }
       BulkCipherAlgorithm;

       enum { stream, block } CipherType;

enum { null, md5, sha } MACAlgorithm;

enum { null(0), (255) } CompressionMethod;

struct {
           ConnectionEnd          entity;
           BulkCipherAlgorithm    bulk_cipher_algorithm;
           CipherType             cipher_type;
           uint8                  key_size;
           uint8                  key_material_length;
           MACAlgorithm           mac_algorithm;
           uint8                  hash_size;
           CompressionMethod      compression_algorithm;
           opaque                 master_secret[48];
           opaque                 client_random[32];
           opaque                 server_random[32];
       } SecurityParameters;

struct {
           uint8 major; uint8 minor;
       } ProtocolVersion;

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

struct {
           ContentType type;
           ProtocolVersion version;
           uint16 length;
           opaque fragment[TLSPlaintext.length];
       } TLSPlaintext;

struct {
           ContentType type;       /* same as TLSPlaintext.type */
           ProtocolVersion version;/* same as TLSPlaintext.version */
           uint16 length;
           opaque fragment[TLSCompressed.length];
       } TLSCompressed;

struct {
           ContentType type;
           ProtocolVersion version;
           uint16 length;
           select (CipherSpec.cipher_type) {
               case stream: GenericStreamCipher;
               case block: GenericBlockCipher;
           } fragment;
       } TLSCiphertext;

stream-ciphered struct {
           opaque content[TLSCompressed.length];
           opaque MAC[CipherSpec.hash_size];
       } GenericStreamCipher;

block-ciphered struct {
           opaque IV[CipherSpec.block_length];
           opaque content[TLSCompressed.length];
           opaque MAC[CipherSpec.hash_size];
           uint8 padding[GenericBlockCipher.padding_length];
           uint8 padding_length;
       } GenericBlockCipher;

enum { change_cipher_spec(1), (255) } ccs_type;

struct {
           ccs_type type;
       } ChangeCipherSpec;

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

struct {
                 AlertLevel level;
                 AlertDescription description;
             } Alert;

enum {
          hello_request(0), client_hello(1), server_hello(2),
          certificate(11), server_key_exchange (12),
          certificate_request(13), server_hello_done(14),
          certificate_verify(15), client_key_exchange(16),
          finished(20), (255)
      } HandshakeType;

struct { } HelloRequest;

struct {
         uint32 gmt_unix_time;
         opaque random_bytes[28];
      } Random;

enum { null(0), (255) } CompressionMethod;

struct {
          ProtocolVersion client_version;
          Random random;
          SessionID session_id;
          CipherSuite cipher_suites<2..2^16-1>;
          CompressionMethod compression_methods<1..2^8-1>;
      } ClientHello;

struct {
           ProtocolVersion server_version;
           Random random;
           SessionID session_id;
           CipherSuite cipher_suite;
           CompressionMethod compression_method;
       } ServerHello;

struct {
          ASN.1Cert certificate_list<0..2^24-1>;
      } Certificate;

enum { rsa, diffie_hellman } KeyExchangeAlgorithm;

struct {
          opaque rsa_modulus<1..2^16-1>;
          opaque rsa_exponent<1..2^16-1>;
      } ServerRSAParams;

struct {
          opaque dh_p<1..2^16-1>;
          opaque dh_g<1..2^16-1>;
          opaque dh_Ys<1..2^16-1>;
      } ServerDHParams;

struct {
          select (KeyExchangeAlgorithm) {
              case diffie_hellman:
                  ServerDHParams params;
                  Signature signed_params;
              case rsa:
                  ServerRSAParams params;
                  Signature signed_params;
          }
      } ServerKeyExchange;

struct {
          select (KeyExchangeAlgorithm) {
              case diffie_hellman:
                  ServerDHParams params;
              case rsa:
                  ServerRSAParams params;
          }
       } ServerParams;

enum { anonymous, rsa, dsa } SignatureAlgorithm;

struct { } anonymous;

digitally-signed struct {
	opaque md5_hash[16];
	opaque sha_hash[20];
} rsa_sig;

digitally-signed struct {
	opaque sha_hash[20];
} dsa_sig;

struct {
          select (SignatureAlgorithm) {
              case anonymous:
                  anonymous sig;
              case rsa:
                  rsa_sig sig;
              case dsa:
		  dsa_sig sig;
          }
      } Signature;

enum {
          rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
       rsa_ephemeral_dh_RESERVED(5), dss_ephemeral_dh_RESERVED(6),
       fortezza_dms_RESERVED(20),
          (255)

      } ClientCertificateType;

struct {
          ClientCertificateType certificate_types<1..2^8-1>;
          DistinguishedName certificate_authorities<0..2^16-1>;
      } CertificateRequest;

struct { } ServerHelloDone;

struct {
          select (KeyExchangeAlgorithm) {
              case rsa:
		EncryptedPreMasterSecret exchange_keys;
              case diffie_hellman:
		ClientDiffieHellmanPublic exchange_keys;
          }
      } ClientKeyExchange;

struct {
          ProtocolVersion client_version;
          opaque random[46];
      } PreMasterSecret;

struct {
          public-key-encrypted PreMasterSecret pre_master_secret;
      } EncryptedPreMasterSecret;

enum { implicit, explicit } PublicValueEncoding;

struct {
          select (PublicValueEncoding) {
              case implicit: struct { };
              case explicit: opaque dh_Yc<1..2^16-1>;
          } dh_public;
      } ClientDiffieHellmanPublic;

struct {
           Signature signature;
      } CertificateVerify;

struct {
          opaque verify_data[12];
      } Finished;

struct {
       uint8 major, minor;
   } ProtocolVersion;

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

struct {
       ContentType type;
       ProtocolVersion version;
       uint16 length;
       opaque fragment[TLSPlaintext.length];
   } TLSPlaintext;

struct {
       ContentType type;
       ProtocolVersion version;
       uint16 length;
       opaque fragment[TLSCompressed.length];
   } TLSCompressed;

struct {
       ContentType type;
       ProtocolVersion version;
       uint16 length;
       select (CipherSpec.cipher_type) {
           case stream: GenericStreamCipher;
           case block:  GenericBlockCipher;
       } fragment;
   } TLSCiphertext;

stream-ciphered struct {
       opaque content[TLSCompressed.length];
       opaque MAC[CipherSpec.hash_size];
   } GenericStreamCipher;

struct {
       enum { change_cipher_spec(1), (255) } type;
   } ChangeCipherSpec;

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

enum {
           close_notify(0),
           unexpected_message(10),
           bad_record_mac(20),
           decryption_failed(21),
           record_overflow(22),
           decompression_failure(30),
           handshake_failure(40),
           no_certificate_RESERVED (41),
           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),
           export_restriction_RESERVED(60),
           protocol_version(70),
           insufficient_security(71),
           internal_error(80),
           user_canceled(90),
           no_renegotiation(100),
           (255)
       } AlertDescription;

struct {
       AlertLevel level;
       AlertDescription description;
   } Alert;

enum {
       hello_request(0), client_hello(1), server_hello(2),
       certificate(11), server_key_exchange (12),
       certificate_request(13), server_hello_done(14),
       certificate_verify(15), client_key_exchange(16),
       finished(20), (255)
   } HandshakeType;

struct {
       HandshakeType msg_type;
       uint24 length;
       select (HandshakeType) {
           case hello_request:       HelloRequest;
           case client_hello:        ClientHello;
           case server_hello:        ServerHello;
           case certificate:         Certificate;
           case server_key_exchange: ServerKeyExchange;
           case certificate_request: CertificateRequest;
           case server_hello_done:   ServerHelloDone;
           case certificate_verify:  CertificateVerify;
           case client_key_exchange: ClientKeyExchange;
           case finished:            Finished;
       } body;
   } Handshake;

struct { } HelloRequest;

struct {
       uint32 gmt_unix_time;
       opaque random_bytes[28];
   } Random;

enum { null(0), (255) } CompressionMethod;

struct {
       ProtocolVersion server_version;
       Random random;
       SessionID session_id;
       CipherSuite cipher_suite;
       CompressionMethod compression_method;
   } ServerHello;

struct {
       ASN.1Cert certificate_list<0..2^24-1>;
   } Certificate;

enum { rsa, diffie_hellman } KeyExchangeAlgorithm;

struct {
       opaque rsa_modulus<1..2^16-1>;
       opaque rsa_exponent<1..2^16-1>;
   } ServerRSAParams;

struct {
       opaque dh_p<1..2^16-1>;
       opaque dh_g<1..2^16-1>;
       opaque dh_Ys<1..2^16-1>;
   } ServerDHParams;

struct {
       select (KeyExchangeAlgorithm) {
           case diffie_hellman:
               ServerDHParams params;
               Signature signed_params;
           case rsa:
               ServerRSAParams params;
               Signature signed_params;
       };
   } ServerKeyExchange;

enum { anonymous, rsa, dsa } SignatureAlgorithm;

struct {
       select (SignatureAlgorithm) {
           case anonymous: struct { };
           case rsa:
               digitally-signed struct {
                   opaque md5_hash[16];
                   opaque sha_hash[20];
               };
           case dsa:
               digitally-signed struct {
                   opaque sha_hash[20];
               };
           };
       };
   } Signature;

enum {
       rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
    rsa_ephemeral_dh_RESERVED(5), dss_ephemeral_dh_RESERVED(6),
    fortezza_dms_RESERVED(20),
    (255)
   } ClientCertificateType;

struct {
       ClientCertificateType certificate_types<1..2^8-1>;
       DistinguishedName certificate_authorities<0..2^16-1>;
   } CertificateRequest;

struct { } ServerHelloDone;

struct {
       select (KeyExchangeAlgorithm) {
           case rsa: EncryptedPreMasterSecret;
           case diffie_hellman: ClientDiffieHellmanPublic;
       } exchange_keys;
   } ClientKeyExchange;

struct {
       ProtocolVersion client_version;
       opaque random[46];
   }
   PreMasterSecret;

   struct {
       public-key-encrypted PreMasterSecret pre_master_secret;
   } EncryptedPreMasterSecret;

enum { implicit, explicit } PublicValueEncoding;

struct {
       select (PublicValueEncoding) {
           case implicit: struct {};
           case explicit: opaque DH_Yc<1..2^16-1>;
       } dh_public;
   } ClientDiffieHellmanPublic;

struct {
       Signature signature;
   } CertificateVerify;

struct {
       opaque verify_data[12];
   } Finished;

enum { null(0), (255) } CompressionMethod;

enum { server, client } ConnectionEnd;

enum { null, rc4, rc2, des, des3, des40, aes, idea }
            BulkCipherAlgorithm;

            enum { stream, block } CipherType;

enum { null, md5, sha } MACAlgorithm;

struct {
                ConnectionEnd entity;
                BulkCipherAlgorithm bulk_cipher_algorithm;
                CipherType cipher_type;
                uint8 key_size;
                uint8 key_material_length;
                MACAlgorithm mac_algorithm;
                uint8 hash_size;
                CompressionMethod compression_algorithm;
                opaque master_secret[48];
                opaque client_random[32];
                opaque server_random[32];
            } SecurityParameters;

struct {
         uint16 msg_length;
         uint8 msg_type;
         Version version;
         uint16 cipher_spec_length;
         uint16 session_id_length;
         uint16 challenge_length;
         V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
         opaque session_id[V2ClientHello.session_id_length];
         opaque challenge[V2ClientHello.challenge_length;
     } V2ClientHello;

