Skip to content
spp_pkt.c 47.4 KiB
Newer Older
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#define USE_SOCKETS
#include "ssl_locl.h"
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/rand.h>

//#define DEBUG
#define MAX_EMPTY_RECORDS 10 /* Might not be needed */
/* Read record from the underlying communication medium 
 * This method attempts to read and decrypt the . */
static int spp_get_record(SSL *s) {
    int ssl_major,ssl_minor,al;
    int enc_err,n,i,ret= -1;
    SSL3_RECORD *rr;
    SSL_SESSION *sess;
    SPP_SLICE *slice;
    SPP_CTX ctx_tmp;
    SPP_CTX *spp_ctx;
    unsigned char *p;
    unsigned char md[EVP_MAX_MD_SIZE];
    short version;
    unsigned mac_size, orig_len;
    size_t extra;
    unsigned empty_record_count = 0;    
    
    rr= &(s->s3->rrec);
    sess=s->session;

    if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
        extra=SSL3_RT_MAX_EXTRA;
    else
        extra=0;
    if (extra && !s->s3->init_extra) {
        /* 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 < SPP_RT_HEADER_LENGTH)) {
            n=ssl3_read_n(s, SPP_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
            if (n <= 0) return(n); /* error or non-blocking */
            s->rstate=SSL_ST_READ_BODY;

            p=s->packet;
#ifdef DEBUG
            fprintf(stderr, "Received record header: ");
            spp_print_buffer(p, SPP_RT_HEADER_LENGTH);
#endif
            /* Pull apart the header into the SSL3_RECORD */
            rr->type= *(p++);
            ssl_major= *(p++);
            ssl_minor= *(p++);
            version=(ssl_major<<8)|ssl_minor;            
            n2s(p,rr->length);
            /* New header fields: slice_id, proxy_id */
            rr->slice_id = *(p++);
            
            if (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
                s->read_stats.handshake_bytes += SPP_RT_HEADER_LENGTH;
            else
                s->read_stats.header_bytes += SPP_RT_HEADER_LENGTH;
            s->read_stats.bytes += rr->length + SPP_RT_HEADER_LENGTH;
#if 0
fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length);
#endif

            /* Lets check version */
            if (!s->first_packet) {
                if (version != s->version) {
                    SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
                    if ((s->version & 0xFF00) == (version & 0xFF00) && !s->enc_write_ctx && !s->write_hash)
                        /* Send back error using their minor version number :-) */
                        s->version = (unsigned short)version;
                    al=SSL_AD_PROTOCOL_VERSION;
                    goto f_err;
                }
            }

            if ((version>>8) != SPP_VERSION_MAJOR) {
                SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
                goto err;
            }

            if (rr->length > s->s3->rbuf.len - SPP_RT_HEADER_LENGTH) {
                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 */

    if (rr->length > s->packet_length-SPP_RT_HEADER_LENGTH) {
        /* now s->packet_length == SPP_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 == SPP_RT_HEADER_LENGTH + rr->length */
    }

    s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */

    /* At this point, s->packet_length == SPP_RT_HEADER_LNGTH + rr->length,
     * and we have that many bytes in s->packet
     */
    rr->input= &(s->packet[SPP_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 > SPP_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;
    slice = SPP_get_slice_by_id(s, rr->slice_id);
    //printf("Receiving record slice %d\n", rr->slice_id);
    /* Get slice from id if it can be found. */
    /*if (!slice) {
        SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
        goto f_err;
    } */    
    s->read_slice = slice;
    
    /* Setup up the ctx for this read 
     * provided that it is for a slice. */
    if (slice != NULL) {
#ifdef DEBUG
        printf("Encrypted packet:");
        spp_print_buffer(rr->data, rr->length);
#endif
        /* If we are not a proxy, use temporary state. */
        if (s->proxy == 1) {
            spp_ctx = (SPP_CTX*)OPENSSL_malloc(sizeof(SPP_CTX));
        } else {        
            spp_ctx = &(ctx_tmp);
        }
        spp_ctx->mac_length=0;
        spp_ctx->integrity_mac=spp_ctx->read_mac=spp_ctx->write_mac=NULL;
        s->spp_read_ctx = spp_ctx;
    } else {
        s->spp_read_ctx = NULL;
    }
    
    /* Send to ssp_enc for decryption. */
    enc_err = s->method->ssl3_enc->enc(s,0);
    
    /* enc_err is:
     *    0: (in non-constant time) if the record is publically invalid.
     *    1: if the padding is valid
     *    -1: if the padding is invalid */
    if (enc_err == 0) {
        al=SSL_AD_DECRYPTION_FAILED;
        SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
        goto f_err;
    }

#ifdef TLS_DEBUG
printf("dec %d\n",rr->length);
{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
printf("\n");
#endif
    
    /*if (slice != NULL) {
        printf("Slice not NULL\n");
        if (EVP_MD_CTX_md(slice->read_mac->read_hash) != NULL) {
            printf("MD not NULL\n");
        }
    }*/
    /* r->length is now the compressed data plus mac */
    /* We can read this record */
    if ((sess != NULL) &&
        (s->enc_read_ctx != NULL) &&
        (slice != NULL) &&
        (EVP_MD_CTX_md(slice->read_mac->read_hash) != NULL)) {
            /* s->read_hash != NULL => mac_size != -1 */
#ifdef DEBUG
            printf("Parsing 3MAC\n");
#endif
Loading
Loading full blame…