Linux安全体系学习笔记之二:OpenSSL源代码分析(1)


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连接结构列出如下:

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.
	 */

	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 */
	};

列出SSL方法结构SSL_METHOD如下:

/* 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;



你可能感兴趣的:(linux,session,ssl,callback,extension,代码分析)