示例#1
0
static void
tls_handshake_ready_callback(tls_handshake_ctx_t ctx, bool write, bool ready)
{
    SSLContext *myCtx = (SSLContext *)ctx;

    sslDebugLog("%p %s ready=%d\n", myCtx, write?"write":"read", ready);

    if(write) {
        myCtx->writeCipher_ready=ready?1:0;
    } else {
        myCtx->readCipher_ready=ready?1:0;
        if(ready) {
            SSLChangeHdskState(myCtx, SSL_HdskStateReady);
        } else {
            SSLChangeHdskState(myCtx, SSL_HdskStatePending);
        }
    }
}
示例#2
0
int
tls_handshake_close(tls_handshake_t filter)
{
	int      err = errSSLSuccess;

    assert(filter);

    err = SSLSendAlert(SSL_AlertLevelWarning, SSL_AlertCloseNotify, filter);

    SSLChangeHdskState(filter, SSL_HdskStateGracefulClose);

    return err;
}
OSStatus
SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
{   OSStatus          err1, err2;

    if(desc != SSL_AlertCloseNotify) {
    	sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc);
    }
    SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);

	if(ctx->negProtocolVersion < TLS_Version_1_0) {
		/* translate to SSL3 if necessary */
		switch(desc) {
			//case SSL_AlertDecryptionFail_RESERVED:
			case SSL_AlertRecordOverflow:
			case SSL_AlertAccessDenied:
			case SSL_AlertDecodeError:
			case SSL_AlertDecryptError:
			//case SSL_AlertExportRestriction_RESERVED:
			case SSL_AlertProtocolVersion:
			case SSL_AlertInsufficientSecurity:
			case SSL_AlertUserCancelled:
			case SSL_AlertNoRenegotiation:
				desc = SSL_AlertHandshakeFail;
				break;
			case SSL_AlertUnknownCA:
				desc = SSL_AlertUnsupportedCert;
				break;
			case SSL_AlertInternalError:
				desc = SSL_AlertCloseNotify;
				break;
			default:
				/* send as is */
				break;
		}
	}
    /* Make session unresumable; I'm not stopping if I get an error,
        because I'd like to attempt to send the alert anyway */
    err1 = SSLDeleteSessionData(ctx);

    /* Second, send the alert */
    err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx);

	ctx->sentFatalAlert = true;

    /* If they both returned errors, arbitrarily return the first */
    return err1 != 0 ? err1 : err2;
}
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 {
OSStatus
SSLProcessChangeCipherSpec(SSLRecord rec, SSLContext *ctx)
{   OSStatus          err;

    if (rec.contents.length != 1 || rec.contents.data[0] != 1)
    {
        if(ctx->isDTLS)
            return errSSLWouldBlock;

        SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx);
    	sslErrorLog("***bad changeCipherSpec msg: length %d data 0x%x\n",
    		(unsigned)rec.contents.length, (unsigned)rec.contents.data[0]);
        return errSSLProtocol;
    }

	/*
	 * Handle PAC-style session resumption, client side only.
	 * In that case, the handshake state was left in either KeyExchange or
	 * Cert.
	 */
	if((ctx->protocolSide == kSSLClientSide) &&
	   (ctx->sessionTicket.length != 0) &&
	   ((ctx->state == SSL_HdskStateKeyExchange) || (ctx->state == SSL_HdskStateCert)) &&
	   (ctx->masterSecretCallback != NULL)) {
		size_t secretLen = SSL_MASTER_SECRET_SIZE;
		sslEapDebug("Client side resuming based on masterSecretCallback");
		ctx->masterSecretCallback(ctx, ctx->masterSecretArg,
			ctx->masterSecret, &secretLen);
		ctx->sessionMatch = 1;

		/* set up selectedCipherSpec */
		if ((err = FindCipherSpec(ctx)) != 0) {
			return err;
		}
		if((err = SSLInitPendingCiphers(ctx)) != 0) {
			SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
			return err;
		}
		SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
	}

    if (!ctx->readPending_ready || ctx->state != SSL_HdskStateChangeCipherSpec)
    {
        if(ctx->isDTLS)
            return errSSLWouldBlock;

        SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx);
    	sslErrorLog("***bad changeCipherSpec msg: readPending.ready %d state %d\n",
		(unsigned)ctx->readPending_ready, (unsigned)ctx->state);
        return errSSLProtocol;
    }

    sslLogNegotiateDebug("===Processing changeCipherSpec msg");

    /* Install new cipher spec on read side */
    if ((err = ctx->recFuncs->advanceReadCipher(ctx->recCtx)) != 0)
    {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
        return err;
    }
    ctx->readCipher_ready = 0;      /* Can't send data until Finished is sent */
    SSLChangeHdskState(ctx, SSL_HdskStateFinished);
    return errSecSuccess;
}
示例#6
0
tls_handshake_t
tls_handshake_create(bool dtls, bool server)
{
    tls_handshake_t ctx;

    ctx=(tls_handshake_t)malloc(sizeof(struct _tls_handshake_s));

    if(ctx == NULL) {
		return NULL;
	}

    memset(ctx, 0, sizeof(struct _tls_handshake_s));

    ctx->state = SSL_HdskStateUninit;
    ctx->retransmit_attempt = 0;
    ctx->clientCertState = kSSLClientCertNone;

    ctx->isDTLS = dtls;
    ctx->mtu = DEFAULT_DTLS_MTU;

    ctx->isServer = server;
	/* Default value so we can send and receive hello msgs */
	ctx->sslTslCalls = &Ssl3Callouts;

    /* Initialize the cipher state to NULL_WITH_NULL_NULL */
    ctx->selectedCipher        = TLS_NULL_WITH_NULL_NULL;
    InitCipherSpecParams(ctx);

    /* 
     * Default configuration
     */
    tls_handshake_set_config(ctx, tls_handshake_config_default);

    /* 
     * Enabled SCT and OCSP extension for client 
     */
    if(!ctx->isServer) {
        tls_handshake_set_sct_enable(ctx, true);
        tls_handshake_set_ocsp_enable(ctx, true);
    }

    tls_handshake_set_ems_enable(ctx, true);
	/*
	 * Initial/default set of ECDH curves
	 */
    tls_handshake_set_curves(ctx, KnownCurves, CurvesCount);
	ctx->ecdhPeerCurve = tls_curve_none;		/* until we negotiate one */
	ctx->negAuthType = tls_client_auth_type_None;		/* ditto */

    /*
     * Initial/default set of SigAlgs
     */
    tls_handshake_set_sigalgs(ctx, KnownSigAlgs, SigAlgsCount);

    if (ctx->isServer) {
        SSLChangeHdskState(ctx, SSL_HdskStateServerUninit);
    } else {
        SSLChangeHdskState(ctx, SSL_HdskStateClientUninit);
    }

	return ctx;
}