管理员
|
阅读:4392回复:0
[系统教程]Linux安全体系学习笔记之二:OpenSSL源代码分析
楼主#
更多
发布于:2011-12-27 11:31
| | | | OpenSSL的源代码包括三部分:加密算法库、SSL库和应用程序。 加密算法库的源代码主要在crypto文件夹里,包括ASN.1编码与解码接口(crypto/asn1/asn1.h),伪随机数产生器(crypto/rand/rand.h),ENGINE机制(crypto/engine),统一密码算法的EVP密码算法接口(crypto/evp/evp.h),大数运算接口(crypto/bn/bn.h),私钥信息语法(crypto/x509/x509.h),非对称密码算法(crypto/rsa/ras.h)等。 SSL库的源代码主要在ssl文件夹里,我们重点分析。 SSL相关的几个重要的数据结构包括: 1、SSL连接结构:核心结构,应用程序通过该结构获取所有其他结构。 2、上下文结构SSL_CTX:是全局的上下文结构,含有结构SSL的主要默认值,包含SSL会话结构。 3、会话结构SSL_SESSION:含有链接的当前TLS/SSL会话细节。 4、密码结构SSL_CIPHER:含有制定的加密算法信息。 5、方法结构SSL_METHOD:功能函数接口,统一了各种SSL协议版本(SSLv1, SSLv2, SSLv3, TLSv1)。 SSL连接结构列出如下: <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 the * 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 for * 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 as * handshake_func is == 0 until then, we use this * test instead of an "init" member. */ www.atcpu.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 actually be a previously * 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 received */ 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 many 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() calls, 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 for * 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; /* Expect 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 received or to be sent */ unsigned char *tlsext_ocsp_resp; int tlsext_ocsp_resplen; /* RFC4507 session ticket expected to be received 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 ctx #endif /* OPENSSL_NO_TLSEXT */ };</span> 列出SSL方法结构SSL_METHOD如下: 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>
| | | | |
|