在ssl_locl.h
中定义了整个协议栈结构的三个非常重要的结构体ssl_ctx_st,ssl_st
以及ssl_method_st
。本次主要分析结构体变量ssl_method_st
,因此其他的结构暂且不表。
在结构体ssl_ctx_st,ssl_st
中均定义了const SSL_METHOD *method
,即ssl_method_st
类型变量,这个变量在协议栈的主流程中频繁的出现,主要是定义了整个流程过程中遇到的一些函数,例如报文数据读写函数等。由于ssl_method_st
结构体中的变量均是函数指针,因此需要搞清楚这些函数指针在什么地方赋值。
通常使用openssl接口都会先调用SSL_CTX_new
以及SSL_new
来生成ssl_ctx_st,ssl_st
着两种类型的变量,其中在SSL_CTX_new
,发现SSL_CTX_new
的入参是一个ssl_method_st
结构类型变量,该入参会被赋值给ssl_ctx
中相应的变量const SSL_METHOD *method,SSL_new
的入参为ssl_ctx_st
类型变量,因此ssl_st
中相应的变量const SSL_METHOD *method
也会被赋值。通常SSL_CTX_new
的调用如下SSL_CTX_new(TLS_server_method())
或者SSL_CTX_new(TLS_client_method())
,但是 TLS_server_method
或者 TLS_client_method
函数只能够找到其声明,找不到其定义。
前面在分析sk以及lhash这两中基本数据结构的时候,也是找不到sk_
以及lhash_
开头的函数定义,当时是为了实现相当于面向对象结构中的继承效果,采用了宏定义的方式。 这次同样采用了宏定义的方式。因为ssl_method_st
结构体中的函数用于处理ssl数据交互,但是由于ssl版本的不同,因此方法便存在着差异。因此除了在include/openssl/ssl.h
中声明的函数外,
__owur const SSL_METHOD *TLS_method(void);
__owur const SSL_METHOD *TLS_client_method(void);
include中的文件主要用于对外提供接口使用 在ssl/ssl_locl.h中也存在着如下声明 :
__owur const SSL_METHOD *sslv3_method(void);
__owur const SSL_METHOD *sslv3_server_method(void);
__owur const SSL_METHOD *sslv3_client_method(void);
__owur const SSL_METHOD *tlsv1_method(void);
__owur const SSL_METHOD *tlsv1_server_method(void);
__owur const SSL_METHOD *tlsv1_client_method(void);
__owur const SSL_METHOD *tlsv1_1_method(void);
__owur const SSL_METHOD *tlsv1_2_method(void);
__owur const SSL_METHOD *tlsv1_3_method(void);
__owur const SSL_METHOD *tlsv1_3_server_method(void);
__owur const SSL_METHOD *tlsv1_3_client_method(void);
表示各种版本的函数声明。 前面已经提到,对于这种类似与继承用法函数定义,一般是应用了宏定义。 在ssl/methods.h中出现了IMPLEMENT_tls_meth_func
宏,例如: MPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, TLS_server_method, ossl_statem_accept, ssl_undefined_function, TLSv1_2_enc_data)
而该宏的第四个参数对应的则是前面所提到的函数声明TLS_server_method
等, 而该宏则定义在ssl/ssl_locl.h,如下:
define IMPLEMENT_tls_meth_func(version, flags, mask, func_name, s_accept, \
s_connect, enc_data) \
const SSL_METHOD *func_name(void)
{
static const SSL_METHOD func_name##_data= {
version,
flags,
mask,
tls1_new,
tls1_clear,
tls1_free,
s_accept,
s_connect,
ssl3_read,
ssl3_peek,
ssl3_write,
ssl3_shutdown,
ssl3_renegotiate,
ssl3_renegotiate_check,
ssl3_read_bytes,
ssl3_write_bytes,
ssl3_dispatch_alert,
ssl3_ctrl,
ssl3_ctx_ctrl,
ssl3_get_cipher_by_char,
ssl3_put_cipher_by_char,
ssl3_pending,
ssl3_num_ciphers,
ssl3_get_cipher,
tls1_default_timeout,
&enc_data,
ssl_undefined_void_function,
ssl3_callback_ctrl,
ssl3_ctx_callback_ctrl,
};
return &func_name##_data;
}
可以看到当入参为TLS_server_method
,则实现了对于SSL_METHOD *TLS_server_method(void);
的定义,前面所述的其余函数则同理会有相应的定义。
而在SSL_METHOD *TLS_server_method(void)
函数中,可以看到返回了一个静态常量 static const SSL_METHOD TLS_server_method_data
,而该常量则会在SSL_CTX_new(TLS_server_method())
中,初始化ssl_ctx_st
结构体类型中的const SSL_METHOD *method
变量。至此,可以看到整个ssl握手过程中所使用到的一些函数均存在于 static const SSL_METHOD TLS_server_method_data中
,这些函数包括tls1_new, tls1_clear, tls1_free,
初始化以及清理函数,主要针对SSL3_STATE
类型变量;s_accept, s_connect
, 服务器和客户端连接的状态机函数。ssl3_read, ssl3_peek, ssl3_write,ssl3_renegotiate, ssl3_renegotiate_check, ssl3_read_bytes, ssl3_write_bytes
, 报文读写以及重协商相关函数;ssl3_ctrl, ssl3_ctx_ctrl,
一些控制函数;ssl3_callback_ctrl,ssl3_ctx_callback_ctrl,
用户可以设置的控制回调函数,enc_data
变量主要是 IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, TLS_server_method, ossl_statem_accept, ssl_undefined_function, TLSv1_2_enc_data)
这类宏传进的最后一个参数 TLSv1_2_enc_data
来决定的,可以看到这是一个全局变量,定义在ssl/t1_lib.c
中,该变量主要定义了ssl3_enc_method
结构体中加解密和摘要等相关算法的封装。在涉及到加解密以及摘要相关部分,再详细说明。
本文为CSDN村中少年原创文章,转载记得加上小尾巴偶,博主链接这里。