예제 #1
0
SECStatus 
sslBuffer_Append(sslBuffer *b, const void * data, unsigned int len)
{
    unsigned int newLen = b->len + len;
    SECStatus rv;

    rv = sslBuffer_Grow(b, newLen);
    if (rv != SECSuccess)
    	return rv;
    PORT_Memcpy(b->buf + b->len, data, len);
    b->len += len;
    return SECSuccess;
}
예제 #2
0
SECStatus
ssl_CreateSecurityInfo(sslSocket *ss)
{
    SECStatus status;

    /* initialize sslv2 socket to send data in the clear. */
    ssl2_UseClearSendFunc(ss);

    ss->sec.blockSize  = 1;
    ss->sec.blockShift = 0;

    ssl_GetXmitBufLock(ss); 
    status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
    ssl_ReleaseXmitBufLock(ss); 

    return status;
}
예제 #3
0
/* ssl3_SendPaddingExtension possibly adds an extension which ensures that a
 * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures
 * that we don't trigger bugs in F5 products.
 *
 * This takes an existing extension buffer, |buf|, and the length of the
 * remainder of the ClientHello, |prefixLen|.  It modifies the extension buffer
 * to insert padding at the right place.
 */
SECStatus
ssl_InsertPaddingExtension(const sslSocket *ss, unsigned int prefixLen,
                           sslBuffer *buf)
{
    static unsigned char padding[252] = { 0 };
    unsigned int paddingLen;
    unsigned int tailLen;
    SECStatus rv;

    /* Account for the size of the header, the length field of the extensions
     * block and the size of the existing extensions. */
    paddingLen = ssl_CalculatePaddingExtLen(ss, prefixLen + 2 + buf->len);
    if (!paddingLen) {
        return SECSuccess;
    }

    /* Move the tail if there is one. This only happens if we are sending the
     * TLS 1.3 PSK extension, which needs to be at the end. */
    if (ss->xtnData.lastXtnOffset) {
        PORT_Assert(buf->len > ss->xtnData.lastXtnOffset);
        tailLen = buf->len - ss->xtnData.lastXtnOffset;
        rv = sslBuffer_Grow(buf, buf->len + 4 + paddingLen);
        if (rv != SECSuccess) {
            return SECFailure;
        }
        PORT_Memmove(buf->buf + ss->xtnData.lastXtnOffset + 4 + paddingLen,
                     buf->buf + ss->xtnData.lastXtnOffset,
                     tailLen);
        buf->len = ss->xtnData.lastXtnOffset;
    } else {
        tailLen = 0;
    }

    rv = sslBuffer_AppendNumber(buf, ssl_padding_xtn, 2);
    if (rv != SECSuccess) {
        return SECFailure; /* Code already set. */
    }
    rv = sslBuffer_AppendVariable(buf, padding, paddingLen, 2);
    if (rv != SECSuccess) {
        return SECFailure; /* Code already set. */
    }

    buf->len += tailLen;

    return SECSuccess;
}
예제 #4
0
SECStatus
ssl_CreateSecurityInfo(sslSocket *ss)
{
    SECStatus status;

    
    ssl2_UseClearSendFunc(ss);

    ss->sec.blockSize  = 1;
    ss->sec.blockShift = 0;

    ssl_GetXmitBufLock(ss); 
    status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
    ssl_ReleaseXmitBufLock(ss); 

    return status;
}
예제 #5
0
/*
 * Attempt to read in an entire SSL3 record.
 * Blocks here for blocking sockets, otherwise returns -1 with
 *  PR_WOULD_BLOCK_ERROR when socket would block.
 *
 * returns  1 if received a complete SSL3 record.
 * returns  0 if recv returns EOF
 * returns -1 if recv returns < 0
 *  (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
 *
 * Caller must hold the recv buf lock.
 *
 * The Gather state machine has 3 states:  GS_INIT, GS_HEADER, GS_DATA.
 * GS_HEADER: waiting for the 5-byte SSL3 record header to come in.
 * GS_DATA:   waiting for the body of the SSL3 record   to come in.
 *
 * This loop returns when either
 *      (a) an error or EOF occurs,
 *  (b) PR_WOULD_BLOCK_ERROR,
 *  (c) data (entire SSL3 record) has been received.
 */
static int
ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
{
    unsigned char *bp;
    unsigned char *lbp;
    int nb;
    int err;
    int rv = 1;

    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
    if (gs->state == GS_INIT) {
        gs->state = GS_HEADER;
        gs->remainder = 5;
        gs->offset = 0;
        gs->writeOffset = 0;
        gs->readOffset = 0;
        gs->inbuf.len = 0;
    }

    lbp = gs->inbuf.buf;
    for (;;) {
        SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)",
                     SSL_GETPID(), ss->fd, gs->state, gs->remainder));
        bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset;
        nb = ssl_DefRecv(ss, bp, gs->remainder, flags);

        if (nb > 0) {
            PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
        } else if (nb == 0) {
            /* EOF */
            SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
            rv = 0;
            break;
        } else /* if (nb < 0) */ {
            SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
                     PR_GetError()));
            rv = SECFailure;
            break;
        }

        PORT_Assert((unsigned int)nb <= gs->remainder);
        if ((unsigned int)nb > gs->remainder) {
            /* ssl_DefRecv is misbehaving!  this error is fatal to SSL. */
            gs->state = GS_INIT; /* so we don't crash next time */
            rv = SECFailure;
            break;
        }

        gs->offset += nb;
        gs->remainder -= nb;
        if (gs->state == GS_DATA)
            gs->inbuf.len += nb;

        /* if there's more to go, read some more. */
        if (gs->remainder > 0) {
            continue;
        }

        /* have received entire record header, or entire record. */
        switch (gs->state) {
            case GS_HEADER:
              /*
              ** Have received SSL3 record header in gs->hdr.
              ** Now extract the length of the following encrypted data,
              ** and then read in the rest of the SSL3 record into gs->inbuf.
              */
                gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];

                /* This is the max fragment length for an encrypted fragment
                ** plus the size of the record header.
                */
                if (gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) {
                    SSL3_SendAlert(ss, alert_fatal, unexpected_message);
                    gs->state = GS_INIT;
                    PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
                    return SECFailure;
                }

                gs->state = GS_DATA;
                gs->offset = 0;
                gs->inbuf.len = 0;

                if (gs->remainder > gs->inbuf.space) {
                    err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
                    if (err) { /* realloc has set error code to no mem. */
                        return err;
                    }
                    lbp = gs->inbuf.buf;
                }
                break; /* End this case.  Continue around the loop. */

            case GS_DATA:
                /*
                ** SSL3 record has been completely received.
                */
                gs->state = GS_INIT;
                return 1;
        }
    }

    return rv;
}
예제 #6
0
/*
 * Read in an entire DTLS record.
 *
 * Blocks here for blocking sockets, otherwise returns -1 with
 *  PR_WOULD_BLOCK_ERROR when socket would block.
 *
 * This is simpler than SSL because we are reading on a datagram socket
 * and datagrams must contain >=1 complete records.
 *
 * returns  1 if received a complete DTLS record.
 * returns  0 if recv returns EOF
 * returns -1 if recv returns < 0
 *  (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
 *
 * Caller must hold the recv buf lock.
 *
 * This loop returns when either
 *      (a) an error or EOF occurs,
 *  (b) PR_WOULD_BLOCK_ERROR,
 *  (c) data (entire DTLS record) has been received.
 */
static int
dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
{
    int nb;
    int err;
    int rv = 1;

    SSL_TRC(30, ("dtls_GatherData"));

    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));

    gs->state = GS_HEADER;
    gs->offset = 0;

    if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */
        gs->dtlsPacketOffset = 0;
        gs->dtlsPacket.len = 0;

        /* Resize to the maximum possible size so we can fit a full datagram */
        /* This is the max fragment length for an encrypted fragment
        ** plus the size of the record header.
        ** This magic constant is copied from ssl3_GatherData, with 5 changed
        ** to 13 (the size of the record header).
        */
        if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) {
            err = sslBuffer_Grow(&gs->dtlsPacket,
                                 MAX_FRAGMENT_LENGTH + 2048 + 13);
            if (err) { /* realloc has set error code to no mem. */
                return err;
            }
        }

        /* recv() needs to read a full datagram at a time */
        nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags);

        if (nb > 0) {
            PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb));
        } else if (nb == 0) {
            /* EOF */
            SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
            rv = 0;
            return rv;
        } else /* if (nb < 0) */ {
            SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
                     PR_GetError()));
            rv = SECFailure;
            return rv;
        }

        gs->dtlsPacket.len = nb;
    }

    /* At this point we should have >=1 complete records lined up in
     * dtlsPacket. Read off the header.
     */
    if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) {
        SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet "
                 "too short to contain header",
                 SSL_GETPID(), ss->fd));
        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
        gs->dtlsPacketOffset = 0;
        gs->dtlsPacket.len = 0;
        rv = SECFailure;
        return rv;
    }
    memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13);
    gs->dtlsPacketOffset += 13;

    /* Have received SSL3 record header in gs->hdr. */
    gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12];

    if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) {
        SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short "
                 "to contain rest of body",
                 SSL_GETPID(), ss->fd));
        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
        gs->dtlsPacketOffset = 0;
        gs->dtlsPacket.len = 0;
        rv = SECFailure;
        return rv;
    }

    /* OK, we have at least one complete packet, copy into inbuf */
    if (gs->remainder > gs->inbuf.space) {
        err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
        if (err) { /* realloc has set error code to no mem. */
            return err;
        }
    }

    memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset,
           gs->remainder);
    gs->inbuf.len = gs->remainder;
    gs->offset = gs->remainder;
    gs->dtlsPacketOffset += gs->remainder;
    gs->state = GS_INIT;

    return 1;
}
예제 #7
0
static SECStatus
ssl_CallCustomExtensionSenders(sslSocket *ss, sslBuffer *buf,
                               SSLHandshakeType message)
{
    sslBuffer tail = SSL_BUFFER_EMPTY;
    SECStatus rv;
    PRCList *cursor;

    /* Save any extensions that want to be last. */
    if (ss->xtnData.lastXtnOffset) {
        rv = sslBuffer_Append(&tail, buf->buf + ss->xtnData.lastXtnOffset,
                              buf->len - ss->xtnData.lastXtnOffset);
        if (rv != SECSuccess) {
            return SECFailure;
        }
        buf->len = ss->xtnData.lastXtnOffset;
    }

    /* Reserve the maximum amount of space possible. */
    rv = sslBuffer_Grow(buf, 65535);
    if (rv != SECSuccess) {
        return SECFailure;
    }

    for (cursor = PR_NEXT_LINK(&ss->extensionHooks);
         cursor != &ss->extensionHooks;
         cursor = PR_NEXT_LINK(cursor)) {
        sslCustomExtensionHooks *hook =
            (sslCustomExtensionHooks *)cursor;
        PRBool append = PR_FALSE;
        unsigned int len = 0;

        if (hook->writer) {
            /* The writer writes directly into |buf|.  Provide space that allows
             * for the existing extensions, any tail, plus type and length. */
            unsigned int space = buf->space - (buf->len + tail.len + 4);
            append = (*hook->writer)(ss->fd, message,
                                     buf->buf + buf->len + 4, &len, space,
                                     hook->writerArg);
            if (len > space) {
                PORT_SetError(SEC_ERROR_APPLICATION_CALLBACK_ERROR);
                goto loser;
            }
        }
        if (!append) {
            continue;
        }

        rv = sslBuffer_AppendNumber(buf, hook->type, 2);
        if (rv != SECSuccess) {
            goto loser; /* Code already set. */
        }
        rv = sslBuffer_AppendNumber(buf, len, 2);
        if (rv != SECSuccess) {
            goto loser; /* Code already set. */
        }
        buf->len += len;

        if (message == ssl_hs_client_hello ||
            message == ssl_hs_certificate_request) {
            ss->xtnData.advertised[ss->xtnData.numAdvertised++] = hook->type;
        }
    }

    rv = sslBuffer_Append(buf, tail.buf, tail.len);
    if (rv != SECSuccess) {
        goto loser; /* Code already set. */
    }

    sslBuffer_Clear(&tail);
    return SECSuccess;

loser:
    sslBuffer_Clear(&tail);
    return SECFailure;
}
예제 #8
0
static int
ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
{
    unsigned char *bp;
    unsigned char *lbp;
    int            nb;
    int            err;
    int            rv		= 1;

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    if (gs->state == GS_INIT) {
        gs->state       = GS_HEADER;
        gs->remainder   = 5;
        gs->offset      = 0;
        gs->writeOffset = 0;
        gs->readOffset  = 0;
        gs->inbuf.len   = 0;
    }

    lbp = gs->inbuf.buf;
    for(;;) {
        SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)",
                     SSL_GETPID(), ss->fd, gs->state, gs->remainder));
        bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset;
        nb = ssl_DefRecv(ss, bp, gs->remainder, flags);

        if (nb > 0) {
            PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
        } else if (nb == 0) {

            SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
            rv = 0;
            break;
        } else  {
            SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
                     PR_GetError()));
            rv = SECFailure;
            break;
        }

        PORT_Assert( nb <= gs->remainder );
        if (nb > gs->remainder) {

            gs->state = GS_INIT;
            rv = SECFailure;
            break;
        }

        gs->offset    += nb;
        gs->remainder -= nb;
        if (gs->state == GS_DATA)
            gs->inbuf.len += nb;


        if (gs->remainder > 0) {
            continue;
        }


        switch (gs->state) {
        case GS_HEADER:
            gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];

            if(gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) {
                SSL3_SendAlert(ss, alert_fatal, unexpected_message);
                gs->state = GS_INIT;
                PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
                return SECFailure;
            }

            gs->state     = GS_DATA;
            gs->offset    = 0;
            gs->inbuf.len = 0;

            if (gs->remainder > gs->inbuf.space) {
                err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
                if (err) {
                    return err;
                }
                lbp = gs->inbuf.buf;
            }
            break;


        case GS_DATA:
            gs->state = GS_INIT;
            return 1;
        }
    }

    return rv;
}
예제 #9
0
static int
dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
{
    int            nb;
    int            err;
    int            rv		= 1;

    SSL_TRC(30, ("dtls_GatherData"));

    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );

    gs->state = GS_HEADER;
    gs->offset = 0;

    if (gs->dtlsPacketOffset == gs->dtlsPacket.len) {
        gs->dtlsPacketOffset = 0;
        gs->dtlsPacket.len = 0;


        if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) {
            err = sslBuffer_Grow(&gs->dtlsPacket,
                                 MAX_FRAGMENT_LENGTH + 2048 + 13);
            if (err) {
                return err;
            }
        }


        nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags);

        if (nb > 0) {
            PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb));
        } else if (nb == 0) {

            SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
            rv = 0;
            return rv;
        } else  {
            SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
                     PR_GetError()));
            rv = SECFailure;
            return rv;
        }

        gs->dtlsPacket.len = nb;
    }

    if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) {
        SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet "
                 "too short to contain header", SSL_GETPID(), ss->fd));
        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
        gs->dtlsPacketOffset = 0;
        gs->dtlsPacket.len = 0;
        rv = SECFailure;
        return rv;
    }
    memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13);
    gs->dtlsPacketOffset += 13;


    gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12];

    if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) {
        SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short "
                 "to contain rest of body", SSL_GETPID(), ss->fd));
        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
        gs->dtlsPacketOffset = 0;
        gs->dtlsPacket.len = 0;
        rv = SECFailure;
        return rv;
    }


    if (gs->remainder > gs->inbuf.space) {
        err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
        if (err) {
            return err;
        }
    }

    memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset,
           gs->remainder);
    gs->inbuf.len = gs->remainder;
    gs->offset = gs->remainder;
    gs->dtlsPacketOffset += gs->remainder;
    gs->state = GS_INIT;

    return 1;
}