From 47be47bf17d481f6a873b96ee0c268ccd2ab1882 Mon Sep 17 00:00:00 2001 From: Derek Pryor Date: Mon, 10 Jul 2006 13:26:20 +0000 Subject: [PATCH] Adding SSL Constructs header file. (First version) --- src/crypto/ssl_constructs.h | 314 ++++++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 src/crypto/ssl_constructs.h diff --git a/src/crypto/ssl_constructs.h b/src/crypto/ssl_constructs.h new file mode 100644 index 00000000..43c58551 --- /dev/null +++ b/src/crypto/ssl_constructs.h @@ -0,0 +1,314 @@ +// Note: This file still needs some work. + +// Typedefs +// (As defined by the SSL v3.0 RFC Draft) +// URL: http://wp.netscape.com/eng/ssl3/draft302.txt +typedef unsigned char uint8; +typedef uint8 uint16[2]; +typedef uint8 uint24[3]; +typedef uint8 uint32[4]; +typedef uint8 uint64[8]; + +// Record layers +typedef struct _ProtocolVersion{ + uint8 major, minor; +} ProtocolVersion; + +ProtocolVersion version = { 3, 0 }; + +typedef enum _ContentType{ + content_type_change_cipher_spec_type=20, + content_type_alert=21, + content_type_handshake=22, + content_type_application_data=23, + content_type_size=255 // to force size +} ContentType; + +typedef struct _SSLPlaintext{ + ContentType type; + ProtocolVersion version; + uint16 length; // can not exceed 2^14 bytes + uint8 fragment[16384]; // 2^14 = 16,384 bytes +} SSLPlaintext; + +typedef struct _SSLCompressed{ + ContentType type; + ProtocolVersion version; + uint16 length; // can not exceed 2^14 + 1024 + uint8 fragment[17408]; // SSLCompressed.length +} SSLCompressed; + +typedef struct _GenericStreamCipher{ + uint8 content[17408]; // SSLCompressed.length + uint8 MAC[]; // CipherSpec.hash_size +} GenericStreamCipher; + +typedef struct _SSLStreamCiphertext{ + ContentType type; + ProtocolVersion version; + uint16 length; // can not exceed 2^14 + 2048 = 18,456 + GenericStreamCipher fragment; +} SSLStreamCiphertext; + +typedef struct _GenericBlockCipher{ + uint8 content[17408]; // SSLConpressed.length + uint8 MAC[0]; // CipherSpec.hash_size + // padding is used to bring the plaintext to + // a multiple of the block cipher's block length. + uint8 padding[0]; // GenericBlockCipher.padding_length + uint8 padding_length; +} GenericBlockCipher; + +typedef struct _SSLBlockCiphertext{ + ContentType type; + ProtocolVersion version; + uint16 length; // can not exceed 2^14 + 2048 = 18,456 + GenericBlockCipher fragment; +} SSLBlockCiphertext; + +// Change cipher specs message +typedef struct _ChangeCipherSpec{ + enum { type_change_cipher_spec=1, type_size=255 } type; +} ChangeCipherSpec; + +// Alert messages +typedef enum _AlertLevel{ + alert_level_warning=1, + alert_level_fatal=2, + alert_level_size=255 +} AlertLevel; + +typedef enum _AlertDescription{ + alert_description_close_notify=0, + alert_description_unexpected_message=10, + alert_description_bad_record_mac=20, + alert_description_decompression_failure=30, + alert_description_handshake_failure=40, + alert_description_no_certificate=41, + alert_description_bad_certificate=42, + alert_description_unsupported_certificate=43, + alert_description_certificate_revoked=44, + alert_description_certificate_expired=45, + alert_description_certificate_unknown=46, + alert_description_illegal_parameter=47, + alert_description_size=255 +} AlertDescription; + +typedef struct _Alert{ + AlertLevel level; + AlertDescription description; +} Alert; + +// Handshake protocol +// What is the best way to have a generic pointer to the body struct?? +typedef enum _HandshakeType{ + handshake_type_hello_request=0, + handshake_type_client_hello=1, + handshake_type_server_hello=2, + handshake_type_certificate=11, + handshake_type_server_key_exchange=12, + handshake_type_certificate_request=13, + handshake_type_server_done=14, + handshake_type_certificate_verify=15, + handshake_type_client_key_exchange=16, + handshake_type_finished=20, + handshake_type_size=255 +} HandshakeType; + +typedef struct _Handshake{ + HandshakeType msg_type; + uint24 length; +} Handshake; // generic Handshake, need to recast to get body + +// Hello messages +typedef struct _HelloRequest{} HelloRequest; + +typedef struct _HelloRequestHandshake{ + HandshakeType msg_type; + uint24 length; + HelloRequest body; +} HelloRequestHandshake; + +typedef struct _Random{ + uint32 gmt_unix_time; + uint8 random_bytes[28]; +} Random; + +typedef uint8 SessionID[32]; // <0..32> +typedef uint8 CipherSuite[2]; + +typedef enum _CompressionMethod{ compression_method_null=0, compression_method_size=255 } CompressionMethod; + +typedef struct _ClientHello{ + ProtocolVersion client_version; + Random random; + SessionID session_id; + CipherSuite cipher_suites[32768]; // <2..2^16-1> = 65,536 bytes and CipherSuite is 2 bytes + CompressionMethod compression_methods[256]; // <0..2^8-1> = 256 bytes and CompressionMethod is 1 byte +} ClientHello; + +typedef struct _ClientHelloHandshake{ + HandshakeType msg_type; + uint24 length; + ClientHello body; +} ClientHelloHandshake; + +typedef struct _ServerHello{ + ProtocolVersion server_version; + Random random; + SessionID session_id; + CipherSuite cipher_suite; + CompressionMethod compression_method; +} ServerHello; + +typedef struct _ServerHelloHandshake{ + HandshakeType msg_type; + uint24 length; + ServerHello body; +} ServerHelloHandshake; + +// Server authentication and key exchange messages +typedef uint8 ASN1Cert[16777216]; // <1..2^24-1> = 16,777,216 bytes + +typedef struct _Certificate{ + ASN1Cert certificate_list[1]; // <1..2^24-1> / ANS1Cert = 1 + // for some reason the size of certificate_list and ASN1Cert is the same, so only one certificate in the list +} Certificate; + +typedef enum _KeyExchangeAlgorithm{ + key_exchange_algorithm_rsa, + key_exchange_algorithm_diffie_hellman, + key_exchange_algorithm_fortezza_kea +} KeyExchangeAlgorithm; + +typedef struct _AnonSignature{ + struct {}; +} AnonSignature; + +typedef struct _RSASignature{ + uint8 md5_hash[16]; + uint8 sha_hash[20]; +} RSASignature; + +typedef struct _DSASignature{ + uint8 sha_hash[20]; +} DSASignature; + +// use union??, make a mess to reference, but easy to make Signature type. +typedef union _Signature{ AnonSignature anon; RSASignature rsa; DSASignature dsa; } Signature; + +typedef struct _ServerRSAParams{ + uint8 RSA_modulus[65536]; // <1..2^16-1> = 65,536 + uint8 RSA_exponent[65536]; // <1..2^16-1> = 65,536 +} ServerRSAParams; + +typedef struct _ServerDHParams{ + uint8 DH_p[65536]; // <1..2^16-1> + uint8 DH_g[65536]; // <1..2^16-1> + uint8 DH_Ys[65536]; // <1..2^16-1> +} ServerDHParams; + +typedef struct _ServerDHKeyExchange{ + ServerDHParams params; + Signature signed_params; +} ServerDHKeyExchange; + +typedef struct _ServerRSAKeyExchange{ + ServerRSAParams params; + Signature signed_params; +} ServerRSAKeyExchange; + +typedef enum _SignatureAlgorithm{ + signature_algorithm_anonymous, + signature_algorithm_rsa, + signature_algorithm_dsa +} SignatureAlgorithm; + +typedef enum _CertificateType{ + certificate_type_RSA_sign=1, + certificate_type_DSS_sign=2, + certificate_type_RSA_fixed_DH=3, + certificate_type_DSS_fixed_DH=4, + certificate_type_RSA_ephemeral_DH=5, + certificate_type_DSS_ephemeral_DH=6, + certificate_type_FORTEZZA_MISSI=20, + certificate_type_size=255 +} CertificateType; + +typedef uint8 DistinguishedName[65536]; // <1..2^16-1> = 65,536 + +typedef struct _CertificateRequest{ + CertificateType certificate_types[256]; // <1..2^8-1> + DistinguishedName certificate_authorities[1]; // <3...2^16-1> / DistinguishedName + // this is another one that is odd with a list size of 1 +} CertificateRequest; + +typedef struct _ServerHelloDone{} ServerHelloDone; + +// Client authentication and key exchange messages +typedef struct _PreMasterSecret{ + ProtocolVersion client_version; + uint8 random[46]; +} PreMasterSecret; + +typedef struct _EncryptedPreMasterSecret{ + PreMasterSecret pre_master_secret; +} EncryptedPreMasterSecret; + +typedef struct _RSAClientKeyExchange{ + EncryptedPreMasterSecret exchange_keys; +} RSAClientKeyExchange; + +typedef enum _PublicValueEncoding{ public_value_encoding_implicit, public_value_encoding_explicit } PublicValueEncoding; + +typedef struct _ClientDiffieHellmanPublic{ + // This is a select on PublicValueEncoding, and I chose the larger size + uint8 dh_public[65536]; // DH_Yc<1..2^16-1>, the dh public value +} ClientDiffieHellmanPublic; + +typedef struct _DHClientKeyExhange{ + ClientDiffieHellmanPublic exchange_keys; +} DHClientKeyExchange; + +typedef struct _CertificateVerify{ + Signature signature; +} CertificateVerify; + +// Handshake finalization message +typedef struct _Finished{ + uint8 md5_hash[16]; + uint8 sha_hash[20]; +} Finished; + +// The CipherSuite +CipherSuite SSL_NULL_WITH_NULL_NULL = { 0x00, 0x00 }; +CipherSuite SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x0B }; +CipherSuite SSL_DH_DSS_WITH_DES_CBC_SHA = { 0x00, 0x0C }; +CipherSuite SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = { 0x00, 0x17 }; +CipherSuite SSL_DH_anon_WITH_RC4_128_MD5 = { 0x00, 0x18 }; + +// The CipherSpec +typedef enum _CipherType{ cipher_type_stream, cipher_type_block } CipherType; +typedef enum _IsExportable{ is_exportable_true, is_exportable_false } IsExportable; +typedef enum _BulkCipherAlgorithm{ + bulk_cipher_algorithm_null, + bulk_cipher_algorithm_rc4, + bulk_cipher_algorithm_rc2, + bulk_cipher_algorithm_des, + bulk_cipher_algorithm_3des, + bulk_cipher_algorithm_des40, + bulk_cipher_algorithm_fortezza +} BulkCipherAlgorithm; +typedef enum _MACAlgorithm{ mac_algorithm_null, mac_algorithm_md5, mac_algorithm_sha } MACAlgorithm; + +typedef struct _CipherSpec{ + BulkCipherAlgorithm bulk_cipher_algorithm; + MACAlgorithm mac_algorithm; + CipherType cipher_type; + IsExportable is_exportable; + uint8 hash_size; + uint8 key_material; + uint8 IV_size; +} CipherSpec; + +