SSL 协议分析:HandShake客户端角度分析(二)

      继续分析SSL协议,上篇介绍的是 客户端握手协议状态机的子状态机“写状态机”,

这篇文章将介绍“读状态机”。 因为“读状态机”就是“写状态机”的下一个跳转状态。

再来看看我画的协议状态机简图:

      从上篇文章结尾处开始继续分析, write_state_machine() 函数(在statem_lib.c文件中)返回

SUB_STATE_FINISHED ,修改state 为 MSG_FLOW_READING 并调用 init_read_state_machine()

函数初始化读取状态机的一些标志:     

      初始化完成后,进入 “读状态机”,简图如下:

      让我们看看 read_state_machine() 代码大致是啥样子的:

      很容易就发现其实和 write_state_machine() 函数是同一个模样,先根据运行的是

客户端代码还是服务端代码初始化函数指针,然后进入“读状态机”。在初始化中我们

得知 read_state 被赋值为 READ_STATE_HEADER ,现在开始分析这个代码块:

      判断是否为DTLS,我用的是TLS ,所以分析 tls_get_message_header() 函数:

//*****************************************************************************

      读取一字节的消息类型: SSL3_RT_HANDSHAKE 或者 SSL3_RT_CHANGE_CIPHER_SPEC;

其他的类型都是错误的 握手包。 可以在 WireShark 抓包中看到,只要是握手包协议,开头第一字节

都是 0x16 ,即 SSL3_RT_HANDSHAKE  的值。

      其实它是在一个循环内找标志数据包类型的标记,识别出数据包类型后循环就退出了。

      赋值消息类型:

      循环退出后,根据接收的数据包协议版本,做不同的指针初始化:

      ok,返回到 read_state_machine() 函数继续分析。如果有回调函数则调用之。然后调用

transition() 指针函数,即 ossl_statem_client_read_transition() 函数。

 

//*****************************************************************************

      这个函数根据从服务器读取的信息,修改握手状态,接收的数据包类型在 mt 参数中,

当前 握手状态 在 s->statem.hand_state 中。

 

       根据 当前握手状态,我们分析 TLS_ST_CW_CLNT_HELLO 基本块。

判断消息类型是否为 SSL3_MT_SERVER_HELLO ,是则修改 握手状态为

TLS_ST_CR_SRVR_HELLO 。正常情况下,客户端发送 ClientHello ,服务器都

会先响应一个 SSL3_MT_SERVER_HELLO  类型的握手数据包。所以在这里我就返回

分析了。

     接着就是修改 read_state ,进入 READ_STATE_BODY 基本块分析。

//*****************************************************************************

      进入 tls_get_message_body() 函数,开始分析:

如果消息类型是 修改密码套件 ,则直接返回。

否则不断的读取数据到缓存中。

如果数据包结束了,就计算消息的 MAC 值,并返回。好了,返回分析到“读状态机”。

初始化缓存,并调用 process_message() 指针函数,即 ossl_statem_client_process_message()函数。

 //*****************************************************************************

进入 ossl_statem_client_process_message() 函数分析:

根据 hand_state 调用不同的处理过程,即不同的握手状态(Hello,证书验证,密钥交换,Finish) ,

调用不同的函数。当前的握手状态是 ServerHello,ok,进入 tls_process_server_hello() 函数分析。

 //*****************************************************************************

     读取两个字节的版本信息,读取服务端随机数,读取会话ID,读取加密方式,压缩方式,

以及扩展信息。可以从 WireShark 解析的协议中,清楚的看见以上信息:

有了服务器发送的加密方式,就设置客户端的加密方式:

 然后解析扩展信息:

最后根据TLS版本调用一些函数,然后返回:

 返回值有多个,根据不同返回值进行不同处理:

在 READ_STATE_POST_PROCESS 块中,发送客户端的证书:

     有了以上的分析,就可以很快理解读取状态机了,最关键的就是判断读取的数据包

是什么类型的握手包(ServerHello,Certificate,KeyExchange,Alert),然后根据

握手包类型,调用不同的处理函数。需要分析的就是 ossl_statem_client_process_message

函数。

猜你喜欢

转载自blog.csdn.net/cwg2552298/article/details/83045448