嵌入式 建立ssl连接过程分析五

原创 2013年12月02日 14:46:38
2.14 SSL_read

SSL结构(structssl_st)中的s2,s3指针分别指向SSL2和SSL3的状态结构,这些状态结构中都有用于读的rbuf,其中保存SSL会话接收到的原始数据,另外还有保存记录的rrec,用来保存解码后的数据。在SSL结构中有个指针packet是指向原始数据的。

SSL_read()实现从SSL通道中读取数据,送到应用程序的数据是已经经过SSL解封装的了。

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()

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, intpeek)
 {
 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表示要读协商数据
  
  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():

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,intval)=NULL;
// 检查是否分配了接收缓冲区
 if (s->s3->rbuf.buf == NULL)
  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))
  
  {
// 握手数据碎片, 处理完直到不再是碎片
  unsigned char *src =s->s3->handshake_fragment;
  unsigned char *dst = buf;
  unsigned int k;
  
  n = 0;
  while ((len > 0) &&(s->s3->handshake_fragment_len > 0))
   {
   *dst++ =*src++;
   len--;s->s3->handshake_fragment_len--;
   n++;
   }
  
  for (k = 0; k <s->s3->handshake_fragment_len; k++)
   s->s3->handshake_fragment[k]= *src++;
  return n;
 }
 
 if (!s->in_handshake &&SSL_in_init(s))
  {
// 没进握手阶段但属于SSL初始化阶段, 调用SSL握手处理
  
  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;
 
// 记录类型指针
 rr = &(s->s3->rrec);
 
 if ((rr->length == 0) || (s->rstate ==SSL_ST_READ_BODY))
  {
// 当前没记录,获取新的记录信息, 该函数获取SSL记录数据
  ret=ssl3_get_record(s);
  if (ret <= 0)return(ret);
  }
 
 if (s->s3->change_cipher_spec
  && (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 (s->shutdown &SSL_RECEIVED_SHUTDOWN)
  {
// 接收到对方的FIN信息, 接收结束
  rr->length=0;
  s->rwstate=SSL_NOTHING;
  return(0);
  }

 if (type == rr->type)
  {
// 读到是数据类型和期待读到的数据类型一致
// 这是正常大多数的情况
  
  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);
   gotof_err;
   }
  if (len <= 0)return(len);
// 在期待读取的数据长度len和已经读到的数据记录长度rr->length取小值作为返回的数据长度
  if ((unsigned int)len >rr->length)
   n =rr->length;
  else
   n = (unsignedint)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);
  }

 
 
// 现在情况是读取的数据类型和期待读取的数据类型不一致
// 已经读到的数据不丢弃,而是作为碎片存储起来以后备用
  {
  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;
// 如果要写入的长度小于可用空间大小,可全部写入
   if(rr->length < n)
    n= rr->length;
// 写入缓冲区
   
   while (n--> 0)
    {
    dest[(*dest_len)++]= rr->data[rr->off++];
    rr->length--;
    }
   if (*dest_len< dest_maxlen)
    gotostart;
   }
  }
 
 
 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);
   gotoerr;
   }
  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)
      {
      BIO*bio;
  
      s->rwstate=SSL_READING;
      bio=SSL_get_rbio(s);
// 清除读BIO重试标志
      BIO_clear_retry_flags(bio);
// 设置读BIO重试标志
      BIO_set_retry_read(bio);
      return(-1);
      }
     }
    }
   }
 
// 重新读数据
  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)
   {
// 普通报警信息
   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)
   {
// 严重错误信息, 断开SSL会话
   chartmp[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,sizeoftmp,"%d",alert_descr);
   ERR_add_error_data(2,"SSLalert 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);
   gotof_err;
   }
  goto start;
  }
 if (s->shutdown & SSL_SENT_SHUTDOWN)
  {
// SSL会话设置发送SHUTDOWN, 表示不再发送数据
  s->rwstate=SSL_NOTHING;
  rr->length=0;
  return(0);
  }
 if (rr->type ==SSL3_RT_CHANGE_CIPHER_SPEC)
  {
// 数据记录类型是更改算法参数
  
  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);
   gotoerr;
   }
  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))
   gotoerr;
  else
   gotostart;
  }
 
 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
   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)
    {
    BIO*bio;
    
    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
  
// 如果会话是TLS1版本转为重新接收数据
// 其他版本则认为出错
  if (s->version ==TLS1_VERSION)
   {
   rr->length= 0;
   gotostart;
   }
#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:
// 这几种类型前面已经处理过了, 到这还有的话是哪出错了
  
  al=SSL_AD_UNEXPECTED_MESSAGE;
  SSLerr(SSL_F_SSL3_READ_BYTES,ERR_R_INTERNAL_ERROR);
  goto f_err;
  caseSSL3_RT_APPLICATION_DATA:
// 这时情况是收到的是应用数据,而期望接收的是握手数据
  
// 要接收应用数据
  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);
   gotof_err;
   }
  }
 
f_err:
// 错误时发送告警信息
 ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
 return(-1);
 }

可以看出接收数据的重点函数是ssl3_get_record():

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
  {

  SSLerr(SSL_F_SSL3_GET_RECORD,ERR_R_INTERNAL_ERROR);
  return -1;
  }
again:
 
 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);
  s->rstate=SSL_ST_READ_BODY;
// p现在是SSL收到的原始数据头
  p=s->packet;
  
// SSL记录类型
  rr->type= *(p++);
// 版本信息
  ssl_major= *(p++);
  ssl_minor= *(p++);
  version=(ssl_major<<8)|ssl_minor;
// 数据长度
  n2s(p,rr->length);
  
  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);
    
    s->version=version;
    al=SSL_AD_PROTOCOL_VERSION;
    gotof_err;
    }
   }
// 检查版本是否是SSL3
  if ((version>>8) !=SSL3_VERSION_MAJOR)
   {
   SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
   gotoerr;
   }
// 接收数据过长出错
  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);
   gotof_err;
   }
  
  }
 
// SSL3_RT_HEADER_LENGTH = 5
 if (rr->length >s->packet_length-SSL3_RT_HEADER_LENGTH)
  {
// 已收到的数据还不够记录长度, 继续读够记录长度
  
  i=rr->length;
  n=ssl3_read_n(s,i,i,1);
  if (n <= 0) return(n);
  
  }
//
// 状态转为已经接收到SSL头信息
 s->rstate=SSL_ST_READ_HEADER;
 
// input指向SSL原始数据头后的数据
 rr->input=&(s->packet[SSL3_RT_HEADER_LENGTH]);
 
 
 
 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;
  }
 
// 记录数据
 rr->data=rr->input;
// 对数据进行解密
 enc_err =s->method->ssl3_enc->enc(s,0);
 if (enc_err <= 0)
  {
  if (enc_err == 0)
   
   gotoerr;
  
// 注意 enc_err<0 时并不立即转到错误处理,只是作个标志
  decryption_failed_or_bad_record_mac= 1;
  }

 
 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
   al=SSL_AD_RECORD_OVERFLOW;
   SSLerr(SSL_F_SSL3_GET_RECORD,
    SSL_R_PRE_MAC_LENGTH_TOO_LONG);
   gotof_err;
#else
// 长度过长, 设置出错标志
   decryption_failed_or_bad_record_mac= 1;
#endif   
   }
  
  if (rr->length >=mac_size)
   {
// 记录长度中减去认证码长度
   rr->length-= mac_size;
// 认证码数据指针
   mac =&rr->data[rr->length];
   }
  else
   {
   
#if 0
   al=SSL_AD_DECODE_ERROR;
   SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
   gotof_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)
  {
// 解密错误, 跳出
  
  al=SSL_AD_BAD_RECORD_MAC;
  SSLerr(SSL_F_SSL3_GET_RECORD, 
   SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
  goto f_err;
  }
 
 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);
   gotof_err;
   }
// 对数据解压
  if (!do_uncompress(s))
   {
// 解压失败, 跳出
   al=SSL_AD_DECOMPRESSION_FAILURE;
   SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
   gotof_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;
 
 
 s->packet_length=0;
 
// 如果记录长度为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的:

static int ssl3_read_n(SSL *s, int n, int max, int extend)
 {
// extend为0时表示要读全新数据,非0表示可以用现在缓冲中的数据
 
 int i,off,newb;
 if (!extend)
  {
  
// 确定包缓冲地址, 置当前的包长为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;
  
  }
 
 if (s->s3->rbuf.left >= (int)n)
  {
// 如果已读缓冲区中剩余数据超过要读的数据,直接移动指针即可
  s->packet_length+=n;
  s->s3->rbuf.left-=n;
  s->s3->rbuf.offset+=n;
  return(n);
  }
 
// 预读数据长度为0
 if (!s->read_ahead)
  max=n;
 {
  
// 当前缓冲区最大空闲值
  int max_max =s->s3->rbuf.len - s->packet_length;
  if (max > max_max)
   max =max_max;
 }
 if (n > max)
  {
// 要读的数据量超过了缓冲区量,出错
  SSLerr(SSL_F_SSL3_READ_N,ERR_R_INTERNAL_ERROR);
  return -1;
  }
 off = s->packet_length;
// newb为读缓冲区中剩下的有效数据长度
 newb = s->s3->rbuf.left;
 
 if (s->packet != s->s3->rbuf.buf)
  {
  
  memmove(s->s3->rbuf.buf,s->packet, off+newb);
  s->packet =s->s3->rbuf.buf;
  }
 while (newb < n)
  {
 
  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;
  }
 
// 读数据完成, 修改偏移量和剩余数据长度
 s->s3->rbuf.offset = off + n;
 s->s3->rbuf.left = newb - n;
 s->packet_length += n;
 s->rwstate=SSL_NOTHING;
 return(n);
 }

相关文章推荐

嵌入式 建立ssl连接过程分析一

Https协议:SSL建立过程分析 web访问的两种方式: http协议,我们一般情况下是通过它访问web,因为它不要求太多的安全机制,使用起来也简单,很多web站点也只支持这种方式下的访问. ...
  • skdkjxy
  • skdkjxy
  • 2013年12月02日 14:46
  • 1193

SSL连接建立过程分析

 Https协议:SSL建立过程分析 web访问的两种方式: http协议,我们一般情况下是通过它访问web,因为它不要求太多的安全机制,使用起来也简单,很多web站点也只支持这种方式下的访...

SSL连接建立过程分析(1)

Https协议:SSL建立过程分析 web访问的两种方式: http协议,我们一般情况下是通过它访问web,因为它不要求太多的安全机制,使用起来也简单,很多web站点也只支持这种方式下的访问. htt...

嵌入式 vlc从接收到数据流到播放视频的过程分析

Vlc流播放流程  vlc源码目录树: 目录名称 说明 bindings Java, CIL 和Python绑定 doc ...
  • cds9527
  • cds9527
  • 2016年12月07日 11:33
  • 1484

Https协议:SSL建立过程分析

web访问的两种方式: http协议,我们一般情况下是通过它访问web,因为它不要求太多的安全机制,使用起来也简单,很多web站点也只支持这种方式下的访问. https协议(Hyperte...
  • gao8658
  • gao8658
  • 2012年05月18日 11:56
  • 2735

Https 建立安全连接的过程(SSL原理)

文中首先解释了加密解密的一些基础知识和概念,然后通过一个加密通信过程的例子说明了加密算法的作用,以及数字证书的出现所起的作用。接着对数字证书做一个详细的解释,并讨论一下windows中数字证书的管理,...

学习嵌入式的过程和基础

C语言是嵌入式最重要的基础知识,但是掌握了它并不代表你的基础已经很好了,嵌入式学习相关的基础知识主要是这些: 一是程序设计的基础,例如:基本的编程语言基础,至少对数据类型、程序的结构及流程控制等最基本...

基于AT91RM9200与LINUX2.6.26内核的嵌入式平台开发全过程

原文来自:http://blog.csdn.net/warmshepherd/article/details/3194127 一、ARM9+LINUX开发历程     使用了51系列和MO...
  • whb_mcu
  • whb_mcu
  • 2012年08月08日 09:53
  • 2205

嵌入式整体开发过程arm

  • 2011年07月03日 09:05
  • 44KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 建立ssl连接过程分析五
举报原因:
原因补充:

(最多只允许输入30个字)