The source code of OpenSSL consists of three parts: the encryption algorithm library, the SSL library, and applications.
The source code of the encryption algorithm library is mainly in the crypto folder, including the ASN.1 encoding and decoding interface (crypto/asn1/asn1.h) and the pseudo random number generator (crypto/rand. h), ENGINE mechanism (crypto/engine), EVP cryptographic algorithm interface (crypto/evp. h), big number operation interface (crypto/bn. h), private key information syntax (crypto/x509/x509.h), asymmetric cipher algorithm (crypto/rsa/ras. h.
The source code of the SSL library is mainly in the ssl folder. We will focus on the analysis.
Several important data structures related to SSL include:
1. SSL connection structure: the core structure through which the application obtains all other structures.
2. Context Structure SSL_CTX: it is a global context structure and contains the main default values of the structure SSL, including the SSL session structure.
3. Session structure SSL_SESSION: contains the details of the current TLS/SSL session of the link.
4. Password structure SSL_CIPHER: contains the specified encryption algorithm information.
5. Method structure SSL_METHOD: function interface, which unifies various SSL protocol versions (SSLv1, SSLv2, SSLv3, TLSv1 ).
The SSL connection structure is listed as follows:
<Span style = "font-size: 18px;"> struct ssl_st
{
/* Protocol version
* (One of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
*/
Int version;
Int type;/* SSL_ST_CONNECT or SSL_ST_ACCEPT */
Const SSL_METHOD * method;/* SSLv3 */
/* There are 2 BIO's even though they are normally both
* Same. This is so data can be read and written to different
* Handlers */
# Ifndef OPENSSL_NO_BIO
BIO * rbio;/* used by SSL_read */
BIO * wbio;/* used by SSL_write */
BIO * bbio;/* used during session-id reuse to concatenate
* Messages */
# Else
Char * rbio;/* used by SSL_read */
Char * wbio;/* used by SSL_write */
Char * bbio;
# Endif
/* This holds a variable that indicates what we were doing
* When a 0 or-1 is returned. This is needed
* Non-blocking IO so we know what request needs re-doing when
* In SSL_accept or SSL_connect */
Int rwstate;
/* True when we are actually in SSL_accept () or SSL_connect ()*/
Int in_handshake;
Int (* handshake_func) (SSL *);
/* Imagine that here's a boolean member "init" that is
* Switched as soon as SSL_set _ {accept/connect} _ state
* Is called for the first time, so that "state" and
* "Handshake_func" are properly initialized. But
* Handshake_func is = 0 until then, we use this
* Test instead of an "init" member.
*/
Www.2cto.com
Int server;/* are we the server side? -Mostly used by SSL_clear */
Int new_session;/* 1 if we are to use a new session.
* 2 if we are a server and are inside a handshake
* (I. e. not just sending a HelloRequest)
* NB: For servers, the 'new' session may be actually a previusly
* Cached session or even the previous session unless
* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
Int quiet_shutdown;/* don't send shutdown packets */
Int shutdown;/* we have shut things down, 0x01 sent, 0x02
* For sorted ed */
Int state;/* where we are */
Int rstate;/* where we are when reading */
BUF_MEM * init_buf;/* buffer used during init */
Void * init_msg;/* pointer to handshake message body, set by ssl3_get_message ()*/
Int init_num;/* amount read/written */
Int init_off;/* amount read/written */
/* Used internally to point at a raw packet */
Unsigned char * packet;
Unsigned int packet_length;
Struct ssl2_state_st * s2;/* SSLv2 variables */
Struct ssl3_state_st * s3;/* SSLv3 variables */
Struct dtls1_state_st * d1;/* DTLSv1 variables */
Int read_ahead;/* Read as your input bytes as possible
* (For non-blocking reads )*/
/* Callback that allows applications to peek at protocol messages */
Void (* msg_callback) (int write_p, int version, int content_type, const void * buf, size_t len, SSL * ssl, void * arg );
Void * msg_callback_arg;
Int hit;/* reusing a previous session */
X509_VERIFY_PARAM * param;
# If 0
Int purpose;/* Purpose setting */
Int trust;/* Trust setting */
# Endif
/* Crypto */
STACK_OF (SSL_CIPHER) * cipher_list;
STACK_OF (SSL_CIPHER) * cipher_list_by_id;
/* These are the ones being used, the ones in SSL_SESSION are
* The ones to be 'copied' into these ones */
Int mac_flags;
EVP_CIPHER_CTX * enc_read_ctx;/* cryptographic state */
EVP_MD_CTX * read_hash;/* used for mac generation */
# Ifndef OPENSSL_NO_COMP
COMP_CTX * expand;/* uncompress */
# Else
Char * expand;
# Endif
EVP_CIPHER_CTX * enc_write_ctx;/* cryptographic state */
EVP_MD_CTX * write_hash;/* used for mac generation */
# Ifndef OPENSSL_NO_COMP
COMP_CTX * compress;/* compression */
# Else
Char * compress;
# Endif
/* Session info */
/* Client cert? */
/* This is used to hold the server certificate used */
Struct cert_st/* CERT */* cert;
/* The session_id_context is used to ensure sessions are only reused
* In the appropriate context */
Unsigned int sid_ctx_length;
Unsigned char sid_ctx [SSL_MAX_SID_CTX_LENGTH];
/* This can also be in the session once a session is established */
SSL_SESSION * session;
/* Default generate session ID callback .*/
GEN_SESSION_CB generate_session_id;
/* Used in SSL2 and SSL3 */
Int verify_mode;/* 0 don't care about verify failure.
* 1 fail if verify fails */
Int (* verify_callback) (int OK, X509_STORE_CTX * ctx);/* fail if callback returns 0 */
Void (* info_callback) (const SSL * ssl, int type, int val);/* optional informational callback */
Int error;/* error bytes to be written */
Int error_code;/* actual code */
# Ifndef OPENSSL_NO_KRB5
KSSL_CTX * kssl_ctx;/* Kerberos 5 context */
# Endif/* OPENSSL_NO_KRB5 */
# Ifndef OPENSSL_NO_PSK
Unsigned int (* psk_client_callback) (SSL * ssl, const char * hint, char * identity,
Unsigned int max_identity_len, unsigned char * psk,
Unsigned int max_psk_len );
Unsigned int (* psk_server_callback) (SSL * ssl, const char * identity,
Unsigned char * psk, unsigned int max_psk_len );
# Endif
SSL_CTX * ctx;
/* Set this flag to 1 and a sleep (1) is put into all SSL_read ()
* And SSL_write () CILS, good for nbio debuging :-)*/
Int debug;
/* Extra application data */
Long verify_result;
CRYPTO_EX_DATA ex_data;
/* For server side, keep the list of CA_dn we can use */
STACK_OF (X509_NAME) * client_CA;
Int references;
Unsigned long options;/* protocol behaviour */
Unsigned long mode;/* API behaviour */
Long max_cert_list;
Int first_packet;
Int client_version;/* what was passed, used
* SSLv3/TLS rollback check */
Unsigned int max_send_fragment;
# Ifndef OPENSSL_NO_TLSEXT
/* TLS extension debug callback */
Void (* tlsext_debug_cb) (SSL * s, int client_server, int type,
Unsigned char * data, int len,
Void * arg );
Void * tlsext_debug_arg;
Char * tlsext_hostname;
Int servername_done;/* no further mod of servername
0: call the servername extension callback.
1: prepare 2, allow last ack just after in server callback.
2: don't call servername callback, no ack in server hello
*/
/* Certificate status request info */
/* Status type or-1 if no status type */
Int tlsext_status_type;
/* Keep ct ocsp CertificateStatus message */
Int tlsext_status_expected;
/* OCSP status request only */
STACK_OF (OCSP_RESPID) * tlsext_ocsp_ids;
X509_EXTENSIONS * tlsext_ocsp_exts;
/* OCSP response encoded ed or to be sent */
Unsigned char * tlsext_ocsp_resp;
Int tlsext_ocsp_resplen;
/* RFC4507 session ticket expected to be encoded ed or sent */
Int tlsext_ticket_expected;
# Ifndef OPENSSL_NO_EC
Size_t tlsext_ecpointformatlist_length;
Unsigned char * tlsext_ecpointformatlist;/* our list */
Size_t tlsext_ellipticcurvelist_length;
Unsigned char * tlsext_ellipticcurvelist;/* our list */
# Endif/* OPENSSL_NO_EC */
/* Draft-rescorla-tls-opaque-prf-input-00.txt information to be used for handshakes */
Void * tlsext_opaque_prf_input;
Size_t tlsext_opaque_prf_input_len;
/* TLS Session Ticket extension override */
TLS_SESSION_TICKET_EXT * tlsext_session_ticket;
/* TLS Session Ticket extension callback */
Tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
Void * tls_session_ticket_ext_cb_arg;
/* TLS pre-shared secret session resumption */
Tls_session_secret_cb_fn tls_session_secret_cb;
Void * tls_session_secret_cb_arg;
SSL_CTX * initial_ctx;/* initial ctx, used to store sessions */
# Define session_ctx initial_ctx
# Else
# Define session_ctx
# Endif/* OPENSSL_NO_TLSEXT */
}; </Span>
The SSL_METHOD for listing the SSL method structure is as follows:
View plain
<Span style = "font-size: 18px;">/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
Typedef struct ssl_method_st
{
Int version;
Int (* ssl_new) (SSL * s );
Void (* ssl_clear) (SSL * s );
Void (* ssl_free) (SSL * s );
Int (* ssl_accept) (SSL * s );
Int (* ssl_connect) (SSL * s );
Int (* ssl_read) (SSL * s, void * buf, int len );
Int (* ssl_peek) (SSL * s, void * buf, int len );
Int (* ssl_write) (SSL * s, const void * buf, int len );
Int (* ssl_shutdown) (SSL * s );
Int (* ssl_renegotiate) (SSL * s );
Int (* ssl_renegotiate_check) (SSL * s );
Long (* ssl_get_message) (SSL * s, int st1, int stn, int mt, long
Max, int * OK );
Int (* ssl_read_bytes) (SSL * s, int type, unsigned char * buf, int len,
Int peek );
Int (* ssl_write_bytes) (SSL * s, int type, const void * buf _, int len );
Int (* ssl_dispatch_alert) (SSL * s );
Long (* ssl_ctrl) (SSL * s, int cmd, long larg, void * parg );
Long (* ssl_ctx_ctrl) (SSL_CTX * ctx, int cmd, long larg, void * parg );
Const SSL_CIPHER * (* get_cipher_by_char) (const unsigned char * ptr );
Int (* put_cipher_by_char) (const SSL_CIPHER * cipher, unsigned char * ptr );
Int (* ssl_pending) (const SSL * s );
Int (* num_ciphers) (void );
Const SSL_CIPHER * (* get_cipher) (unsigned ncipher );
Const struct ssl_method_st * (* get_ssl_method) (int version );
Long (* get_timeout) (void );
Struct ssl3_enc_method * ssl3_enc;/* Extra SSLv3/TLS stuff */
Int (* ssl_version) (void );
Long (* ssl_callback_ctrl) (SSL * s, int cb_id, void (* fp) (void ));
Long (* ssl_ctx_callback_ctrl) (SSL_CTX * s, int cb_id, void (* fp) (void ));
} SSL_METHOD; </span>
From Aegeaner's column