SSL连接建立过程分析(5)
2.14 SSL_read
SSL结构(struct
ssl_st)中的s2,s3指针分别指向SSL2和SSL3的状态结构,这些状态结构中都有用于读的rbuf,其中保存SSL会话接收到的原始数据,另
外还有保存记录的rrec,用来保存解码后的数据。在SSL结构中有个指针packet是指向原始数据的。
SSL_read()实现从SSL通道中读取数据,送到应用程序的数据是已经经过SSL解封装的了。
/* ssl/ssl_lib.c */
int SSL_read(SSL *s,void *buf,int num)
{
if (s->handshake_func == 0)
{
SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED);
return -1;
}
// 发现接收shutdown标志,接收结束
if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
{
s->rwstate=SSL_NOTHING;
return(0);
}
// 调用具体方法的接收函数, 如ssl3_read(), ssl2_read()等
return(s->method->ssl_read(s,buf,num));
}
下面以ssl3_read()函数进行详细说明,ssl3_read()函数本质是调用ssl3_read_internal()
/* ssl/s3_lib.c */
int ssl3_read(SSL *s, void *buf, int len)
{
// 最后一个参数为0,表示是实实在在的读数据,不是偷看(peek)
// peek的意思是读数据,但不会把已读数据从缓冲区中去掉,因此下一次读还会读到
return ssl3_read_internal(s, buf, len, 0);
}
static int ssl3_read_internal(SSL *s, void *buf, int len, int peek)
{
int ret;
// 清除错误信息
clear_sys_error();
// 检查协商是否成功
if (s->s3->renegotiate) ssl3_renegotiate_check(s);
// 标志现在在读应用层数据
s->s3->in_read_app_data=1;
// ssl3读取数据, 类型是SSL3_RT_APPLICATION_DATA,应用数据
ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
if ((ret == -1) && (s->s3->in_read_app_data == 2))
{
// s->s3->in_read_app_data == 2表示要读协商数据
/* ssl3_read_bytes decided to call s->handshake_func, which
* called ssl3_read_bytes to read handshake data.
* However, ssl3_read_bytes actually found application data
* and thinks that application data makes sense here; so disable
* handshake processing and try to read application data again. */
s->in_handshake++;
// 重新读数据
ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
s->in_handshake--;
}
else
s->s3->in_read_app_data=0;
return(ret);
}
读取数据的主要函数实际为ssl3_read_bytes():
/* ssl/ssl3_pkt.c */
int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
{
int al,i,j,ret;
unsigned int n;
SSL3_RECORD *rr;
void (*cb)(const SSL *ssl,int type2,int val)=NULL;
// 检查是否分配了接收缓冲区
if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
if (!ssl3_setup_buffers(s))
return(-1);
// 只处理两种数据,或是应用层数据或者是SSL握手协商数据,
// peek只处理应用层数据,其他则出错
if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
(type != SSL3_RT_HANDSHAKE) && type) ||
(peek && (type != SSL3_RT_APPLICATION_DATA)))
{
SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR);
return -1;
}
if ((type == SSL3_RT_HANDSHAKE) && (s->s3->handshake_fragment_len > 0))
/* (partially) satisfy request from storage */
{
// 握手数据碎片, 处理完直到不再是碎片
unsigned char *src = s->s3->handshake_fragment;
unsigned char *dst = buf;
unsigned int k;
/* peek == 0 */
n = 0;
while ((len > 0) && (s->s3->handshake_fragment_len > 0))
{
*dst++ = *src++;
len--; s->s3->handshake_fragment_len--;
n++;
}
/* move any remaining fragment bytes: */
for (k = 0; k < s->s3->handshake_fragment_len; k++)
s->s3->handshake_fragment[k] = *src++;
return n;
}
/* Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
if (!s->in_handshake && SSL_in_init(s))
{
// 没进握手阶段但属于SSL初始化阶段, 调用SSL握手处理
/* type == SSL3_RT_APPLICATION_DATA */
i=s->handshake_func(s);
if (i < 0) return(i);
if (i == 0)
{
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
return(-1);
}
}
start:
// 正常的接收数据开始, 开始读写状态为NOTHING
s->rwstate=SSL_NOTHING;
/* s->s3->rrec.type - is the type of record
* s->s3->rrec.data, - data
* s->s3->rrec.off, - offset into 'data' for next read
* s->s3->rrec.length, - number of bytes. */
// 记录类型指针
rr = &(s->s3->rrec);
/* get new packet if necessary */
if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
{
// 当前没记录,获取新的记录信息, 该函数获取SSL记录数据
ret=ssl3_get_record(s);
if (ret <= 0) return(ret);
}
/* we now have a packet which can be read and processed */
if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
* reset by ssl3_get_finished */
&& (rr->type != SSL3_RT_HANDSHAKE))
{
// 只允许在握手状态下修改当前的算法信息,否则出错
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
goto err;
}
/* If the other end has shut down, throw anything we read away
* (even in 'peek' mode) */
if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
{
// 接收到对方的FIN信息, 接收结束
rr->length=0;
s->rwstate=SSL_NOTHING;
return(0);
}
if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
{
// 读到是数据类型和期待读到的数据类型一致
// 这是正常大多数的情况
/* make sure that we are not getting application data when we
* are doing a handshake for the first time */
if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
(s->enc_read_ctx == NULL))
{
// 在初始阶段只应该读握手信息而不该读应用信息
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);
goto f_err;
}
if (len <= 0) return(len);
// 在期待读取的数据长度len和已经读到的数据记录长度rr->length取小值作为返回的数据长度
if ((unsigned int)len > rr->length)
n = rr->length;
else
n = (unsigned int)len;
memcpy(buf,&(rr->data[rr->off]),n);
if (!peek)
{
// 如果不是peek,移动记录缓冲的数据偏移指针,长度减
rr->length-=n;
rr->off+=n;
if (rr->length == 0)
{
s->rstate=SSL_ST_READ_HEADER;
rr->off=0;
}
}
// 正常返回
return(n);
}
/* If we get here, then type != rr->type; if we have a handshake
* message, then it was unexpected (Hello Request or Client Hello). */
/* In case of record types for which we have 'fragment' storage,
* fill that so that we can process the data at a fixed place.
*/
// 现在情况是读取的数据类型和期待读取的数据类型不一致
// 已经读到的数据不丢弃,而是作为碎片存储起来以后备用
{
unsigned int dest_maxlen = 0;
unsigned char *dest = NULL;
unsigned int *dest_len = NULL;
if (rr->type == SSL3_RT_HANDSHAKE)
{
// 握手类型数据存到握手碎片区
dest_maxlen = sizeof s->s3->handshake_fragment;
dest = s->s3->handshake_fragment;
dest_len = &s->s3->handshake_fragment_len;
}
else if (rr->type == SSL3_RT_ALERT)
{
// 告警信息存到告警碎片区
dest_maxlen = sizeof s->s3->alert_fragment;
dest = s->s3->alert_fragment;
dest_len = &s->s3->alert_fragment_len;
}
if (dest_maxlen > 0)
{
// 有缓冲区, 计算可用的最大缓冲区
n = dest_maxlen - *dest_len; /* available space in 'dest' */
// 如果要写入的长度小于可用空间大小,可全部写入
if (rr->length < n)
n = rr->length; /* available bytes */
// 写入缓冲区
/* now move 'n' bytes: */
while (n-- > 0)
{
dest[(*dest_len)++] = rr->data[rr->off++];
rr->length--;
}
if (*dest_len < dest_maxlen)
goto start; /* fragment was too small */
}
}
/* s->s3->handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE;
* s->s3->alert_fragment_len == 2 iff rr->type == SSL3_RT_ALERT.
* (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */
/* If we are a client, check for an incoming 'Hello Request': */
if ((!s->server) &&
(s->s3->handshake_fragment_len >= 4) &&
(s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
(s->session != NULL) && (s->session->cipher != NULL))
{
// 本地是客户端
// 握手碎片长度至少是4字节, 类型是HELLO的握手信息时进行处理
s->s3->handshake_fragment_len = 0;
if ((s->s3->handshake_fragment[1] != 0) ||
(s->s3->handshake_fragment[2] != 0) ||
(s->s3->handshake_fragment[3] != 0))
{
// SSL3_MT_HELLO_REQUEST类型后三个字节都要是0
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_HELLO_REQUEST);
goto err;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->s3->handshake_fragment, 4, s, s->msg_callback_arg);
if (SSL_is_init_finished(s) &&
// 协商结束但没设置不需重协商算法标志
!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
// 没设置该ssl3会话的重协商标志
!s->s3->renegotiate)
{
// 进行ssl3重协商,实际是将s->s3->renegotiate置1
ssl3_renegotiate(s);
if (ssl3_renegotiate_check(s))
{
// 进行重协商
i=s->handshake_func(s);
if (i < 0) return(i);
if (i == 0)
{
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
return(-1);
}
if (!(s->mode & SSL_MODE_AUTO_RETRY))
// 该SSL会话不是自动重试模式
{
if (s->s3->rbuf.left == 0) /* no read-ahead left? */
{
BIO *bio;
/* In the case where we try to read application data,
* but we trigger an SSL handshake, we return -1 with
* the retry option set. Otherwise renegotiation may
* cause nasty problems in the blocking world */
s->rwstate=SSL_READING;
bio=SSL_get_rbio(s);
// 清除读BIO重试标志
BIO_clear_retry_flags(bio);
// 设置读BIO重试标志
BIO_set_retry_read(bio);
return(-1);
}
}
}
}
/* we either finished a handshake or ignored the request,
* now try again to obtain the (application) data we were asked for */
// 重新读数据
goto start;
}
if (s->s3->alert_fragment_len >= 2)
{
// 处理告警碎片信息, 长度大于等于2字节时就处理
int alert_level = s->s3->alert_fragment[0];
int alert_descr = s->s3->alert_fragment[1];
s->s3->alert_fragment_len = 0;
// 分别处理msg和info的回调
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_ALERT, s->s3->alert_fragment, 2, s, s->msg_callback_arg);
if (s->info_callback != NULL)
cb=s->info_callback;
else if (s->ctx->info_callback != NULL)
cb=s->ctx->info_callback;
if (cb != NULL)
{
j = (alert_level << 8) | alert_descr;
cb(s, SSL_CB_READ_ALERT, j);
}
if (alert_level == 1) /* warning */
{
// 普通报警信息
s->s3->warn_alert = alert_descr;
if (alert_descr == SSL_AD_CLOSE_NOTIFY)
{
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return(0);
}
}
else if (alert_level == 2) /* fatal */
{
// 严重错误信息, 断开SSL会话
char tmp[16];
s->rwstate=SSL_NOTHING;
s->s3->fatal_alert = alert_descr;
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr);
ERR_add_error_data(2,"SSL alert number ",tmp);
s->shutdown|=SSL_RECEIVED_SHUTDOWN;
SSL_CTX_remove_session(s->ctx,s->session);
return(0);
}
else
{
al=SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
goto f_err;
}
goto start;
}
if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */
{
// SSL会话设置发送SHUTDOWN, 表示不再发送数据
s->rwstate=SSL_NOTHING;
rr->length=0;
return(0);
}
if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
{
// 数据记录类型是更改算法参数
/* 'Change Cipher Spec' is just a single byte, so we know
* exactly what the record payload has to look like */
if ( (rr->length != 1) || (rr->off != 0) ||
(rr->data[0] != SSL3_MT_CCS))
{
// 错误检查
i=SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
goto err;
}
rr->length=0;
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, s->msg_callback_arg);
// 加密算法更改处理,成功时转到重新接收数据
s->s3->change_cipher_spec=1;
if (!do_change_cipher_spec(s))
goto err;
else
goto start;
}
/* Unexpected handshake message (Client Hello, or protocol violation) */
if ((s->s3->handshake_fragment_len >= 4) && !s->in_handshake)
{
// 异常的握手信息
// SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS标志表示不需要重新协商加密算法
if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
{
#if 0 /* worked only because C operator preferences are not as expected (and
* because this is not really needed for clients except for detecting
* protocol violations): */
s->state=SSL_ST_BEFORE|(s->server)
?SSL_ST_ACCEPT
:SSL_ST_CONNECT;
#else
// 如果是服务器端,SSL状态转为接受;如果是客户端, 转为连接
s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
#endif
// 重新进行新会话
s->new_session=1;
}
// 重新握手协商
i=s->handshake_func(s);
if (i < 0) return(i);
if (i == 0)
{
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
return(-1);
}
if (!(s->mode & SSL_MODE_AUTO_RETRY))
{
if (s->s3->rbuf.left == 0) /* no read-ahead left? */
{
BIO *bio;
/* In the case where we try to read application data,
* but we trigger an SSL handshake, we return -1 with
* the retry option set. Otherwise renegotiation may
* cause nasty problems in the blocking world */
s->rwstate=SSL_READING;
bio=SSL_get_rbio(s);
BIO_clear_retry_flags(bio);
BIO_set_retry_read(bio);
return(-1);
}
}
goto start;
}
// 最后再根据记录类型进行处理
switch (rr->type)
{
default:
#ifndef OPENSSL_NO_TLS
/* TLS just ignores unknown message types */
// 如果会话是TLS1版本转为重新接收数据
// 其他版本则认为出错
if (s->version == TLS1_VERSION)
{
rr->length = 0;
goto start;
}
#endif
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
goto f_err;
case SSL3_RT_CHANGE_CIPHER_SPEC:
case SSL3_RT_ALERT:
case SSL3_RT_HANDSHAKE:
// 这几种类型前面已经处理过了, 到这还有的话是哪出错了
/* we already handled all of these, with the possible exception
* of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that
* should not happen when type != rr->type */
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_READ_BYTES,ERR_R_INTERNAL_ERROR);
goto f_err;
case SSL3_RT_APPLICATION_DATA:
// 这时情况是收到的是应用数据,而期望接收的是握手数据
/* At this point, we were expecting handshake data,
* but have application data. If the library was
* running inside ssl3_read() (i.e. in_read_app_data
* is set) and it makes sense to read application data
* at this point (session renegotiation not yet started),
* we will indulge it.
*/
// 要接收应用数据
if (s->s3->in_read_app_data &&
// 需要重协商
(s->s3->total_renegotiations != 0) &&
((
(s->state & SSL_ST_CONNECT) &&
(s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
(s->state <= SSL3_ST_CR_SRVR_HELLO_A)
) || (
(s->state & SSL_ST_ACCEPT) &&
(s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
(s->state >= SSL3_ST_SR_CLNT_HELLO_A)
)
))
{
// in_read_app_data设置为2,会重新执行ssl3_read_bytes()
s->s3->in_read_app_data=2;
return(-1);
}
else
{
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
goto f_err;
}
}
/* not reached */
f_err:
// 错误时发送告警信息
ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
return(-1);
}
可以看出接收数据的重点函数是ssl3_get_record():
/* ssl/s3_pkt.c */
static int ssl3_get_record(SSL *s)
{
int ssl_major,ssl_minor,al;
int enc_err,n,i,ret= -1;
SSL3_RECORD *rr;
SSL_SESSION *sess;
unsigned char *p;
unsigned char md[EVP_MAX_MD_SIZE];
short version;
unsigned int mac_size;
int clear=0;
size_t extra;
int decryption_failed_or_bad_record_mac = 0;
unsigned char *mac = NULL;
// 所读数据的记录指针
rr= &(s->s3->rrec);
sess=s->session;
if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
// MS的SSL实现可附带较大数据
extra=SSL3_RT_MAX_EXTRA;
else
extra=0;
if (extra != s->s3->rbuf.len - SSL3_RT_MAX_PACKET_SIZE)
// 普通情况下读缓冲大小就是SSL3_RT_MAX_PACKET_SIZE
{
/* actually likely an application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER
* set after ssl3_setup_buffers() was done */
SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR);
return -1;
}
again:
/* check if we have the header */
if ( (s->rstate != SSL_ST_READ_BODY) ||
// 接收的数据长度还不够记录长度
(s->packet_length < SSL3_RT_HEADER_LENGTH))
{
// 读至少SSL3_RT_HEADER_LENGTH长度,最大s->s3->rbuf.len
n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
if (n <= 0) return(n); /* error or non-blocking */
s->rstate=SSL_ST_READ_BODY;
// p现在是SSL收到的原始数据头
p=s->packet;
/* Pull apart the header into the SSL3_RECORD */
// SSL记录类型
rr->type= *(p++);
// 版本信息
ssl_major= *(p++);
ssl_minor= *(p++);
version=(ssl_major<<8)|ssl_minor;
// 数据长度
n2s(p,rr->length);
/* Lets check version */
if (s->first_packet)
{
s->first_packet=0;
}
else
{
// 已经不是第一个包了
// 检查版本是否等于SSL会话版本,这时应该协商好应该是相同的了
// 如果不同就是错的
if (version != s->version)
{
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
/* Send back error using their
* version number :-) */
s->version=version;
al=SSL_AD_PROTOCOL_VERSION;
goto f_err;
}
}
// 检查版本是否是SSL3
if ((version>>8) != SSL3_VERSION_MAJOR)
{
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
goto err;
}
// 接收数据过长出错
if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra)
{
al=SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG);
goto f_err;
}
/* now s->rstate == SSL_ST_READ_BODY */
}
/* s->rstate == SSL_ST_READ_BODY, get and decode the data */
// SSL3_RT_HEADER_LENGTH = 5
if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH)
{
// 已收到的数据还不够记录长度, 继续读够记录长度
/* now s->packet_length == SSL3_RT_HEADER_LENGTH */
i=rr->length;
n=ssl3_read_n(s,i,i,1);
if (n <= 0) return(n); /* error or non-blocking io */
/* now n == rr->length,
* and s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length */
}
//
// 状态转为已经接收到SSL头信息
s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */
/* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
* and we have that many bytes in s->packet
*/
// input指向SSL原始数据头后的数据
rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]);
/* ok, we can now read from 's->packet' data into 'rr'
* rr->input points at rr->length bytes, which
* need to be copied into rr->data by either
* the decryption or by the decompression
* When the data is 'copied' into the rr->data buffer,
* rr->input will be pointed at the new buffer */
/* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
* rr->length bytes of encrypted compressed stuff. */
/* check is not needed I believe */
if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra)
{
// 数据又读多了
al=SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
goto f_err;
}
/* decrypt in place in 'rr->input' */
// 记录数据
rr->data=rr->input;
// 对数据进行解密
enc_err = s->method->ssl3_enc->enc(s,0);
if (enc_err <= 0)
{
if (enc_err == 0)
/* SSLerr() and ssl3_send_alert() have been called */
goto err;
/* Otherwise enc_err == -1, which indicates bad padding
* (rec->length has not been changed in this case).
* To minimize information leaked via timing, we will perform
* the MAC computation anyway. */
// 注意 enc_err<0 时并不立即转到错误处理,只是作个标志
decryption_failed_or_bad_record_mac = 1;
}
/* r->length is now the compressed data plus mac */
if ( (sess == NULL) ||
(s->enc_read_ctx == NULL) ||
(s->read_hash == NULL))
// 会话,加密上下文,读认证码操作都为空的情况,设置标志clear
clear=1;
if (!clear)
{
// HASH算法的认证码长度
mac_size=EVP_MD_size(s->read_hash);
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
{
#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */
al=SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD,
SSL_R_PRE_MAC_LENGTH_TOO_LONG);
goto f_err;
#else
// 长度过长, 设置出错标志
decryption_failed_or_bad_record_mac = 1;
#endif
}
/* check the MAC for rr->input (it's in mac_size bytes at the tail) */
if (rr->length >= mac_size)
{
// 记录长度中减去认证码长度
rr->length -= mac_size;
// 认证码数据指针
mac = &rr->data[rr->length];
}
else
{
/* record (minus padding) is too short to contain a MAC */
#if 0 /* OK only for stream ciphers */
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
goto f_err;
#else
// 记录长度还没认证码长度长, 设置出错标志
decryption_failed_or_bad_record_mac = 1;
rr->length = 0;
#endif
}
// 用认证码对数据进行认证
i=s->method->ssl3_enc->mac(s,md,0);
if (mac == NULL || memcmp(md, mac, mac_size) != 0)
{
decryption_failed_or_bad_record_mac = 1;
}
}
if (decryption_failed_or_bad_record_mac)
{
// 解密错误, 跳出
/* A separate 'decryption_failed' alert was introduced with TLS 1.0,
* SSL 3.0 only has 'bad_record_mac'. But unless a decryption
* failure is directly visible from the ciphertext anyway,
* we should not reveal which kind of error occured -- this
* might become visible to an attacker (e.g. via a logfile) */
al=SSL_AD_BAD_RECORD_MAC;
SSLerr(SSL_F_SSL3_GET_RECORD,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
goto f_err;
}
/* r->length is now just compressed */
if (s->expand != NULL)
// 现在数据是经过压缩处理的
{
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra)
{
// 压缩数据长度又太长了
al=SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD,
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
goto f_err;
}
// 对数据解压
if (!do_uncompress(s))
{
// 解压失败, 跳出
al=SSL_AD_DECOMPRESSION_FAILURE;
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
goto f_err;
}
}
if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra)
{
// 解压缩后的明文数据长度过长, 跳出
al=SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
goto f_err;
}
rr->off=0;
/* So at this point the following is true
* ssl->s3->rrec.type is the type of record
* ssl->s3->rrec.length == number of bytes in record
* ssl->s3->rrec.off == offset to first valid byte
* ssl->s3->rrec.data == where to take bytes from, increment
* after use :-).
*/
/* we have pulled in a full packet so zero things */
s->packet_length=0;
/* just read a 0 length packet */
// 如果记录长度为0, 转到继续接收数据
if (rr->length == 0) goto again;
return(1);
f_err:
// 错误发送告警信息
ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
return(ret);
}
最后看一下ssl3_read_n()函数,接收SSL原始数据, 该函数只被ssl3_get_record()函数调用,是static的:
/* ssl/s3_pkt.c */
static int ssl3_read_n(SSL *s, int n, int max, int extend)
{
// extend为0时表示要读全新数据,非0表示可以用现在缓冲中的数据
/* If extend == 0, obtain new n-byte packet; if extend == 1, increase
* packet by another n bytes.
* The packet will be in the sub-array of s->s3->rbuf.buf specified
* by s->packet and s->packet_length.
* (If s->read_ahead is set, 'max' bytes may be stored in rbuf
* [plus s->packet_length bytes if extend == 1].)
*/
int i,off,newb;
if (!extend)
{
/* start with empty packet ... */
// 确定包缓冲地址, 置当前的包长为0
if (s->s3->rbuf.left == 0)
s->s3->rbuf.offset = 0;
s->packet = s->s3->rbuf.buf + s->s3->rbuf.offset;
s->packet_length = 0;
/* ... now we can act as if 'extend' was set */
}
/* if there is enough in the buffer from a previous read, take some */
if (s->s3->rbuf.left >= (int)n)
{
// 如果已读缓冲区中剩余数据超过要读的数据,直接移动指针即可
s->packet_length+=n;
s->s3->rbuf.left-=n;
s->s3->rbuf.offset+=n;
return(n);
}
/* else we need to read more data */
// 预读数据长度为0
if (!s->read_ahead)
max=n;
{
/* avoid buffer overflow */
// 当前缓冲区最大空闲值
int max_max = s->s3->rbuf.len - s->packet_length;
if (max > max_max)
max = max_max;
}
if (n > max) /* does not happen */
{
// 要读的数据量超过了缓冲区量,出错
SSLerr(SSL_F_SSL3_READ_N,ERR_R_INTERNAL_ERROR);
return -1;
}
off = s->packet_length;
// newb为读缓冲区中剩下的有效数据长度
newb = s->s3->rbuf.left;
/* Move any available bytes to front of buffer:
* 'off' bytes already pointed to by 'packet',
* 'newb' extra ones at the end */
if (s->packet != s->s3->rbuf.buf)
{
/* off > 0 */
memmove(s->s3->rbuf.buf, s->packet, off+newb);
s->packet = s->s3->rbuf.buf;
}
while (newb < n)
{
/* Now we have off+newb bytes at the front of s->s3->rbuf.buf and need
* to read in more until we have off+n (up to off+max if possible) */
clear_sys_error();
if (s->rbio != NULL)
{
s->rwstate=SSL_READING;
// 通过SSL的读BIO读取数据
i=BIO_read(s->rbio, &(s->s3->rbuf.buf[off+newb]), max-newb);
}
else
{
SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET);
i = -1;
}
if (i <= 0)
{
// 读完或出错, newb为缓冲区剩余有效数据长度
s->s3->rbuf.left = newb;
return(i);
}
newb+=i;
}
/* done reading, now the book-keeping */
// 读数据完成, 修改偏移量和剩余数据长度
s->s3->rbuf.offset = off + n;
s->s3->rbuf.left = newb - n;
s->packet_length += n;
s->rwstate=SSL_NOTHING;
return(n);
}
...... 待续 ......