Esempio n. 1
0
int
tls_record_decrypt(tls_record_t ctx,
                          const tls_buffer input,
                          tls_buffer *output,
                          uint8_t *contentType)
{
    int        err;
    tls_buffer       cipherFragment;
    uint8_t         *charPtr;
    uint64_t        seqNum;
    uint8_t         ct;
    charPtr=input.data;

    check(input.length>=header_size(ctx));

    if(input.length<header_size(ctx))
        return errSSLRecordParam;

    ct = *charPtr++;
#if 0 // We dont actually check the record protocol version
    tls_protocol_version pv;
    pv = SSLDecodeInt(charPtr, 2);
#endif
    charPtr+=2;
    if(ctx->isDTLS) {
        seqNum = SSLDecodeUInt64(charPtr, 8); charPtr+=8;
    }

    cipherFragment.length = SSLDecodeInt(charPtr, 2); charPtr+=2;
    cipherFragment.data = charPtr;

#if 0 // This is too strict for the record layer.
    if (ct < tls_record_type_V3_Smallest ||
        ct > tls_record_type_V3_Largest)
        return errSSLRecordProtocol;

    if ((ctx->negProtocolVersion != tls_protocol_version_Undertermined) &&
        (pv != ctx->negProtocolVersion)) {
        sslErrorLog("invalid record protocol version, expected = %04x, received = %04x", ctx->negProtocolVersion, pv);
        return errSSLRecordProtocol; // Invalid record version ?
    }
#endif

    check(input.length>=header_size(ctx)+cipherFragment.length);

    if(input.length<header_size(ctx)+cipherFragment.length) {
        return errSSLRecordParam; // input buffer not enough data
    }

    if(ctx->isDTLS)
    {
        /* if the epoch of the record is different of current read cipher, just drop it */
        if((seqNum>>48)!=(ctx->readCipher.sequenceNum>>48)) {
            return errSSLRecordUnexpectedRecord;
        } else {
            ctx->readCipher.sequenceNum=seqNum;
        }
    }
Esempio n. 2
0
int
SSLDecodeBufferList(uint8_t *p, size_t listLen, int itemLenSize, tls_buffer_list_t **list)
{
    int err = 0;

    tls_buffer_list_t *first = NULL;
    tls_buffer_list_t *last = NULL;

    while (listLen > 0)
    {
        size_t itemLen;
        tls_buffer_list_t *item;
        if (listLen < itemLenSize) {
            sslErrorLog("SSLDecodeBufferList: length decode error 2\n");
            err = errSSLProtocol;
            goto errOut;
        }
        itemLen = SSLDecodeInt(p,itemLenSize);
        p += itemLenSize;
        if (listLen < itemLen + itemLenSize) {
            sslErrorLog("SSLDecodeBufferList: length decode error 3\n");
            err = errSSLProtocol;
            goto errOut;
        }
        if(itemLen==0) {
            sslErrorLog("SSLDecodeBufferList: lenght decode error 4 (empty item)\n");
            err = errSSLProtocol;
            goto errOut;
        }
        item = (tls_buffer_list_t *)sslMalloc(sizeof(tls_buffer_list_t));
        if(item == NULL) {
            err = errSSLAllocate;
            goto errOut;
        }
        if ((err = SSLAllocBuffer(&item->buffer, itemLen))) {
            sslFree(item);
            goto errOut;
        }
        item->next = NULL;
        memcpy(item->buffer.data, p, itemLen);
        p += itemLen;

        if(first==NULL) {
            first=item;
            last=item;
        } else {
            last->next=item;
            last=item;
        }
        listLen -= itemLenSize+itemLen;
    }

    *list = first;
    return 0;

errOut:
    tls_free_buffer_list(first);
    return err;
}
Esempio n. 3
0
int
SSLProcessCertificateRequest(tls_buffer message, tls_handshake_t ctx)
{
    unsigned        i;
    unsigned	    typeCount;
    unsigned		shListLen = 0;
    UInt8           *charPtr;
    unsigned		dnListLen;
	unsigned		dnLen;
    tls_buffer		dnBuf;
    DNListElem		*dn;
	int		err;

    /*
     * Cert request only happens in during client authentication.
     * Application can send a client cert if they have an appropriate one.
     * coreTLS does not ensure the client cert is appropriate.
     */

    unsigned minLen = (sslVersionIsLikeTls12(ctx)) ? 5 : 3;
    if (message.length < minLen) {
    	sslErrorLog("SSLProcessCertificateRequest: length decode error 1\n");
        return errSSLProtocol;
    }
    charPtr = message.data;
    typeCount = *charPtr++;
    if ((typeCount < 1) || (message.length < minLen + typeCount)) {
    	sslErrorLog("SSLProcessCertificateRequest: length decode error 2\n");
        return errSSLProtocol;
    }

    /* Update the server-specified auth types */
    sslFree(ctx->clientAuthTypes);
    ctx->numAuthTypes = typeCount;
    ctx->clientAuthTypes = (tls_client_auth_type *)
                           sslMalloc(ctx->numAuthTypes * sizeof(tls_client_auth_type));
    if(ctx->clientAuthTypes==NULL)
        return errSSLInternal;

    for(i=0; i<ctx->numAuthTypes; i++) {
        sslLogNegotiateDebug("===Server specifies authType %d", (int)(*charPtr));
        ctx->clientAuthTypes[i] = (tls_client_auth_type)(*charPtr++);
    }

    if (sslVersionIsLikeTls12(ctx)) {
        /* Parse the supported_signature_algorithms field added in TLS1.2 */
        shListLen = SSLDecodeInt(charPtr, 2);
        charPtr += 2;
        if ((shListLen < 2) || (message.length < minLen + typeCount + shListLen)) {
            sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n");
            return errSSLProtocol;
        }

        if (shListLen & 1) {
            sslErrorLog("SSLProcessCertificateRequest: signAlg len odd\n");
            return errSSLProtocol;
        }

        sslFree(ctx->peerSigAlgs);
        ctx->numPeerSigAlgs = shListLen / 2;
        ctx->peerSigAlgs = (tls_signature_and_hash_algorithm *)
                              sslMalloc((ctx->numPeerSigAlgs) * sizeof(tls_signature_and_hash_algorithm));
        if(ctx->peerSigAlgs==NULL)
            return errSSLInternal;

        for(i=0; i<ctx->numPeerSigAlgs; i++) {
            ctx->peerSigAlgs[i].hash = *charPtr++;
            ctx->peerSigAlgs[i].signature = *charPtr++;
            sslLogNegotiateDebug("===Server specifies sigAlg %d %d",
                                 ctx->peerSigAlgs[i].hash,
                                 ctx->peerSigAlgs[i].signature);
        }
    }

    /* Update the acceptable DNList */
    SSLFreeDNList(ctx->acceptableDNList);
    ctx->acceptableDNList=NULL;

    dnListLen = SSLDecodeInt(charPtr, 2);
    charPtr += 2;
    if (message.length != minLen + typeCount + shListLen + dnListLen) {
    	sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n");
        return errSSLProtocol;
	}
    while (dnListLen > 0)
    {   if (dnListLen < 2) {
		sslErrorLog("SSLProcessCertificateRequest: dnListLen error 1\n");
            return errSSLProtocol;
        }
        dnLen = SSLDecodeInt(charPtr, 2);
        charPtr += 2;
        if (dnListLen < 2 + dnLen) {
     		sslErrorLog("SSLProcessCertificateRequest: dnListLen error 2\n");
           	return errSSLProtocol;
    	}
        if ((err = SSLAllocBuffer(&dnBuf, sizeof(DNListElem))))
            return err;
        dn = (DNListElem*)dnBuf.data;
        if ((err = SSLAllocBuffer(&dn->derDN, dnLen)))
        {   SSLFreeBuffer(&dnBuf);
            return err;
        }
        memcpy(dn->derDN.data, charPtr, dnLen);
        charPtr += dnLen;
        dn->next = ctx->acceptableDNList;
        ctx->acceptableDNList = dn;
        dnListLen -= 2 + dnLen;
    }

    assert(charPtr == message.data + message.length);

    return errSSLSuccess;
}
Esempio n. 4
0
int
SSLProcessCertificate(tls_buffer message, tls_handshake_t ctx)
{
    size_t          listLen;
    UInt8           *p;
    int        err = 0;
    SSLCertificate *certChain;

    if (message.length < 3) {
        sslErrorLog("SSLProcessCertificate: message length decode error\n");
        return errSSLProtocol;
    }

    p = message.data;
    listLen = SSLDecodeInt(p,3);
    p += 3;
    if (listLen + 3 != message.length) {
    	sslErrorLog("SSLProcessCertificate: length decode error 1\n");
        return errSSLProtocol;
    }

    // Note: An empty certificate list (listLen==0) is allowed by the TLS RFC,
    // but empty certificates (certLen==0) are not. Section 7.4.2 in RFC 5246
    // defines the message syntax as such:
    //
    //  opaque ASN.1Cert<1..2^24-1>;
    //
    //  struct {
    //        ASN.1Cert certificate_list<0..2^24-1>;
    //  } Certificate;
    //
    // Note the difference between <1..2^24-1> and <0..2^24-1>
    //

    if((err = SSLDecodeBufferList(p, listLen, 3, (tls_buffer_list_t **)&certChain))) {
        return err;
    }
    p+=listLen;

    /* Do not accept a different server cert during renegotiation unless allowed */
    if(!ctx->allowServerIdentityChange && ctx->peerCert && !CertificateChainEqual(ctx->peerCert, certChain)) {
        sslErrorLog("Illegal server identity change during renegotiation\n");
        SSLFreeCertificates(certChain);
        return errSSLProtocol;
    }

    if (ctx->peerCert == NULL && __ssl_debug_enabled("sslLogNegotiateDebug")) {
        debug_log_chain("sslLogNegotiateDebug", certChain);
    }

    /* Free certs if they already exist */
    SSLFreeCertificates(ctx->peerCert);
    ctx->peerCert=certChain;

    assert(p == message.data + message.length);

    /* Don't fail here if peerCert is NULL.
       An empty Certificate message is valid in some cases.
       The rest of the stack will handle it. */

    return err;
}
static int SSLRecordReadInternal(SSLRecordContextRef ref, SSLRecord *rec)
{   int        err;
    size_t          len, contentLen;
    uint8_t           *charPtr;
    SSLBuffer       readData, cipherFragment;
    size_t          head=5;
    int             skipit=0;
    struct SSLRecordInternalContext *ctx = ref;

    if(ctx->isDTLS)
        head+=8;

    if (!ctx->partialReadBuffer.data || ctx->partialReadBuffer.length < head)
    {   if (ctx->partialReadBuffer.data)
        if ((err = SSLFreeBuffer(&ctx->partialReadBuffer)) != 0)
        {
            return err;
        }
        if ((err = SSLAllocBuffer(&ctx->partialReadBuffer,
                                  DEFAULT_BUFFER_SIZE)) != 0)
        {
            return err;
        }
    }

    if (ctx->negProtocolVersion == SSL_Version_Undetermined) {
        if (ctx->amountRead < 1)
        {   readData.length = 1 - ctx->amountRead;
            readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
            len = readData.length;
            err = sslIoRead(readData, &len, ctx);
            if(err != 0)
            {   if (err == errSSLRecordWouldBlock) {
                ctx->amountRead += len;
                return err;
            }
            else {
                /* abort */
                err = errSSLRecordClosedAbort;
#if 0 // TODO: revisit this in the transport layer
                if((ctx->protocolSide == kSSLClientSide) &&
                   (ctx->amountRead == 0) &&
                   (len == 0)) {
                    /*
                     * Detect "server refused to even try to negotiate"
                     * error, when the server drops the connection before
                     * sending a single byte.
                     */
                    switch(ctx->state) {
                        case SSL_HdskStateServerHello:
                            sslHdskStateDebug("Server dropped initial connection\n");
                            err = errSSLConnectionRefused;
                            break;
                        default:
                            break;
                    }
                }
#endif
                return err;
            }
            }
            ctx->amountRead += len;
        }
    }

    if (ctx->amountRead < head)
    {   readData.length = head - ctx->amountRead;
        readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
        len = readData.length;
        err = sslIoRead(readData, &len, ctx);
        if(err != 0)
        {
			switch(err) {
				case errSSLRecordWouldBlock:
					ctx->amountRead += len;
					break;
#if	SSL_ALLOW_UNNOTICED_DISCONNECT
				case errSSLClosedGraceful:
					/* legal if we're on record boundary and we've gotten past
					 * the handshake */
					if((ctx->amountRead == 0) && 				/* nothing pending */
					   (len == 0) &&							/* nothing new */
					   (ctx->state == SSL_HdskStateClientReady)) {	/* handshake done */
					    /*
						 * This means that the server has disconnected without
						 * sending a closure alert notice. This is technically
						 * illegal per the SSL3 spec, but about half of the
						 * servers out there do it, so we report it as a separate
						 * error which most clients - including (currently)
						 * URLAccess - ignore by treating it the same as
						 * a errSSLClosedGraceful error. Paranoid
						 * clients can detect it and handle it however they
						 * want to.
						 */
						SSLChangeHdskState(ctx, SSL_HdskStateNoNotifyClose);
						err = errSSLClosedNoNotify;
						break;
					}
					else {
						/* illegal disconnect */
						err = errSSLClosedAbort;
						/* and drop thru to default: fatal alert */
					}
#endif	/* SSL_ALLOW_UNNOTICED_DISCONNECT */
				default:
					break;
            }
            return err;
        }
        ctx->amountRead += len;
    }

    check(ctx->amountRead >= head);

    charPtr = ctx->partialReadBuffer.data;
    rec->contentType = *charPtr++;
    if (rec->contentType < SSL_RecordTypeV3_Smallest ||
        rec->contentType > SSL_RecordTypeV3_Largest)
        return errSSLRecordProtocol;

    rec->protocolVersion = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2);
    charPtr += 2;

    if(rec->protocolVersion == DTLS_Version_1_0)
    {
        sslUint64 seqNum;
        SSLDecodeUInt64(charPtr, 8, &seqNum);
        charPtr += 8;
        sslLogRecordIo("Read DTLS Record %016llx (seq is: %016llx)",
                       seqNum, ctx->readCipher.sequenceNum);

        /* if the epoch of the record is different of current read cipher, just drop it */
        if((seqNum>>48)!=(ctx->readCipher.sequenceNum>>48)) {
            skipit=1;
        } else {