s3_pkt.c
来自「一个用于点对点传输加密的工具包源码」· C语言 代码 · 共 1,199 行 · 第 1/3 页
C
1,199 行
al=SSL_AD_DECOMPRESSION_FAILURE; SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION); goto f_err; } } if (rr->length > (unsigned int)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 */ if (rr->length == 0) goto again; return(1);f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al);err: return(ret); }static int do_uncompress(SSL *ssl) { int i; SSL3_RECORD *rr; rr= &(ssl->s3->rrec); i=COMP_expand_block(ssl->expand,rr->comp, SSL3_RT_MAX_PLAIN_LENGTH,rr->data,(int)rr->length); if (i < 0) return(0); else rr->length=i; rr->data=rr->comp; return(1); }static int do_compress(SSL *ssl) { int i; SSL3_RECORD *wr; wr= &(ssl->s3->wrec); i=COMP_compress_block(ssl->compress,wr->data, SSL3_RT_MAX_COMPRESSED_LENGTH, wr->input,(int)wr->length); if (i < 0) return(0); else wr->length=i; wr->input=wr->data; return(1); }/* Call this to write data in records of type 'type' * It will return <= 0 if not all data has been sent or non-blocking IO. */int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) { const unsigned char *buf=buf_; unsigned int tot,n,nw; int i; s->rwstate=SSL_NOTHING; tot=s->s3->wnum; s->s3->wnum=0; if (SSL_in_init(s) && !s->in_handshake) { i=s->handshake_func(s); if (i < 0) return(i); if (i == 0) { SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); return(-1); } } n=(len-tot); for (;;) { if (n > SSL3_RT_MAX_PLAIN_LENGTH) nw=SSL3_RT_MAX_PLAIN_LENGTH; else nw=n; i=do_ssl3_write(s,type,&(buf[tot]),nw); if (i <= 0) { s->s3->wnum=tot; return(i); } if ((i == (int)n) || (type == SSL3_RT_APPLICATION_DATA && (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) { return(tot+i); } n-=i; tot+=i; } }static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) { unsigned char *p,*plen; int i,mac_size,clear=0; SSL3_RECORD *wr; SSL3_BUFFER *wb; SSL_SESSION *sess; /* first check is there is a SSL3_RECORD still being written * out. This will happen with non blocking IO */ if (s->s3->wbuf.left != 0) return(ssl3_write_pending(s,type,buf,len)); /* If we have an alert to send, lets send it */ if (s->s3->alert_dispatch) { i=ssl3_dispatch_alert(s); if (i <= 0) return(i); /* if it went, fall through and send more stuff */ } if (len == 0) return(len); wr= &(s->s3->wrec); wb= &(s->s3->wbuf); sess=s->session; if ( (sess == NULL) || (s->enc_write_ctx == NULL) || (s->write_hash == NULL)) clear=1; if (clear) mac_size=0; else mac_size=EVP_MD_size(s->write_hash); p=wb->buf; /* write the header */ *(p++)=type&0xff; wr->type=type; *(p++)=(s->version>>8); *(p++)=s->version&0xff; /* record where we are to write out packet length */ plen=p; p+=2; /* lets setup the record stuff. */ wr->data=p; wr->length=(int)len; wr->input=(unsigned char *)buf; /* we now 'read' from wr->input, wr->length bytes into * wr->data */ /* first we compress */ if (s->compress != NULL) { if (!do_compress(s)) { SSLerr(SSL_F_DO_SSL3_WRITE,SSL_R_COMPRESSION_FAILURE); goto err; } } else { memcpy(wr->data,wr->input,wr->length); wr->input=wr->data; } /* we should still have the output to wr->data and the input * from wr->input. Length should be wr->length. * wr->data still points in the wb->buf */ if (mac_size != 0) { s->method->ssl3_enc->mac(s,&(p[wr->length]),1); wr->length+=mac_size; wr->input=p; wr->data=p; } /* ssl3_enc can only have an error on read */ s->method->ssl3_enc->enc(s,1); /* record length after mac and block padding */ s2n(wr->length,plen); /* we should now have * wr->data pointing to the encrypted data, which is * wr->length long */ wr->type=type; /* not needed but helps for debugging */ wr->length+=SSL3_RT_HEADER_LENGTH; /* Now lets setup wb */ wb->left=wr->length; wb->offset=0; s->s3->wpend_tot=len; s->s3->wpend_buf=buf; s->s3->wpend_type=type; s->s3->wpend_ret=len; /* we now just need to write the buffer */ return(ssl3_write_pending(s,type,buf,len));err: return(-1); }/* if s->s3->wbuf.left != 0, we need to call this */static int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, unsigned int len) { int i;/* XXXX */ if ((s->s3->wpend_tot > (int)len) || ((s->s3->wpend_buf != buf) && !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) || (s->s3->wpend_type != type)) { SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY); return(-1); } for (;;) { clear_sys_error(); if (s->wbio != NULL) { s->rwstate=SSL_WRITING; i=BIO_write(s->wbio, (char *)&(s->s3->wbuf.buf[s->s3->wbuf.offset]), (unsigned int)s->s3->wbuf.left); } else { SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BIO_NOT_SET); i= -1; } if (i == s->s3->wbuf.left) { s->s3->wbuf.left=0; s->rwstate=SSL_NOTHING; return(s->s3->wpend_ret); } else if (i <= 0) return(i); s->s3->wbuf.offset+=i; s->s3->wbuf.left-=i; } }/* Return up to 'len' payload bytes received in 'type' records. * 'type' is one of the following: * * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) * - 0 (during a shutdown, no data has to be returned) * * If we don't have stored data to work from, read a SSL/TLS record first * (possibly multiple records if we still don't have anything to return). * * This function must handle any surprises the peer may have for us, such as * Alert records (e.g. close_notify), ChangeCipherSpec records (not really * a surprise, but handled as if it were), or renegotiation requests. * Also if record payloads contain fragments too small to process, we store * them until there is enough for the respective protocol (the record protocol * may use arbitrary fragmentation and even interleaving): * Change cipher spec protocol * just 1 byte needed, no need for keeping anything stored * Alert protocol * 2 bytes needed (AlertLevel, AlertDescription) * Handshake protocol * 4 bytes needed (HandshakeType, uint24 length) -- we just have * to detect unexpected Client Hello and Hello Request messages * here, anything else is handled by higher layers * Application data protocol * none of our business */int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len) { int al,i,j,ret; unsigned int n; SSL3_RECORD *rr; void (*cb)()=NULL; if (s->s3->rbuf.buf == NULL) /* Not initialized yet */ if (!ssl3_setup_buffers(s)) return(-1); if ((type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type) { SSLerr(SSL_F_SSL3_READ_BYTES, SSL_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; 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)) { /* 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: 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 ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) { 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 shutdown, throw anything we read away */ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?