Ejemplo n.º 1
0
static void SessionCacheEntryDelete(SessionCacheEntry *entry)
{
	sslLogSessCacheDebug("~SessionCacheEntryDelete() %p", entry);
	SSLFreeBuffer(&entry->mKey, NULL);		// no SSLContext
	SSLFreeBuffer(&entry->mSessionData, NULL);
    free(entry);
}
Ejemplo n.º 2
0
/*
 * This constructor, the only one, allocs copies of the key and value
 * SSLBuffers.
 */
static SessionCacheEntry *SessionCacheEntryCreate(
	const SSLBuffer *key, 
	const SSLBuffer *sessionData,
	CFAbsoluteTime expirationTime)
{
    OSStatus serr;

    SessionCacheEntry *entry = malloc(sizeof(SessionCacheEntry));
    if (entry == NULL)
        return NULL;

	serr = SSLCopyBuffer(key, &entry->mKey);
	if(serr) {
        free (entry);
        return NULL;
	}
	serr = SSLCopyBuffer(sessionData, &entry->mSessionData);
	if(serr) {
        SSLFreeBuffer(&entry->mKey, NULL);
        free (entry);
        return NULL;
	}

	sslLogSessCacheDebug("SessionCacheEntryCreate(buf,buf) %p", entry);
	entry->mExpiration = expirationTime;

    return entry;
}
Ejemplo n.º 3
0
/* Server: set ocsp response data */
int
tls_handshake_set_ocsp_response(tls_handshake_t filter, tls_buffer *ocsp_response)
{
    assert(filter->isServer);
    SSLFreeBuffer(&filter->ocsp_response);
    return SSLCopyBuffer(ocsp_response, &filter->ocsp_response);
}
OSStatus
SSLSendAlert(AlertLevel level, AlertDescription desc, SSLContext *ctx)
{   SSLRecord       rec;
    OSStatus        err;

	switch(ctx->negProtocolVersion) {
		case SSL_Version_Undetermined:
			/* Too early in negotiation to send an alert */
			return errSecSuccess;
		case SSL_Version_2_0:
			/* shouldn't be here */
			assert(0);
			return errSSLInternal;
		default:
			break;
	}
	if(ctx->sentFatalAlert) {
		/* no more alerts allowed */
		return errSecSuccess;
	}
    if ((err = SSLEncodeAlert(&rec, level, desc, ctx)) != 0)
        return err;
	SSLLogAlertMsg(desc, true);
    if ((err = SSLWriteRecord(rec, ctx)) != 0)
        return err;
    if ((err = SSLFreeBuffer(&rec.contents)))
        return err;
    if(desc == SSL_AlertCloseNotify) {
		/* no more alerts allowed */
		ctx->sentFatalAlert = true;
	}
    return errSecSuccess;
}
Ejemplo n.º 5
0
int
tls_handshake_set_peer_hostname(tls_handshake_t filter, const char *hostname, size_t len)
{
    assert(!filter->isServer);
    SSLFreeBuffer(&filter->peerDomainName); // in case you set it twice
    return SSLCopyBufferTerm(hostname, len, &filter->peerDomainName);
}
Ejemplo n.º 6
0
/* Client: set ocsp request_extensions */
int
tls_handshake_set_ocsp_request_extensions(tls_handshake_t filter, tls_buffer ocsp_request_extensions)
{
    assert(!filter->isServer);
    SSLFreeBuffer(&filter->ocsp_request_extensions);
    return SSLCopyBuffer(&ocsp_request_extensions, &filter->ocsp_request_extensions);
}
Ejemplo n.º 7
0
/*
 * Provide an opaque SessionTicket for use in PAC-based session
 * resumption. Client side only. The provided ticket is sent in
 * the ClientHello message as a SessionTicket extension.
 *
 * We won't reject this on the server side, but server-side support
 * for PAC-based session resumption is currently enabled for
 * Development builds only. To fully support this for server side,
 * besides the rudimentary support that's here for Development builds,
 * we'd need a getter for the session ticket, so the app code can
 * access the SessionTicket when its SSLInternalMasterSecretFunction
 * callback is called.
 */
int tls_handshake_internal_set_session_ticket(tls_handshake_t ctx, const void *ticket, size_t ticketLength)
{
    if(ticketLength > 0xffff) {
        /* extension data encoded with a 2-byte length! */
        return errSSLParam;
    }
    SSLFreeBuffer(&ctx->externalSessionTicket);
    return SSLCopyBufferFromData(ticket, ticketLength, &ctx->externalSessionTicket);
}
/* Free SSLCertificate array created by parseIncomingCerts */
static int freeCertificates(SSLCertificate *certs)
{
    SSLCertificate *head = certs;
    while(certs) {
        SSLFreeBuffer(&certs->derCert);
        certs = certs->next;
    }
    sslFree(head);
    return 0;
}
Ejemplo n.º 9
0
/* (re)handshake */
int
tls_handshake_negotiate(tls_handshake_t filter, tls_buffer *peerID)
{
    assert(!filter->isServer);

    if ((filter->state != SSL_HdskStateClientReady) && (filter->state != SSL_HdskStateClientUninit))
    {
        sslDebugLog("Requesting renegotiation while handshake in progress...");
        return errSSLIllegalParam; // TODO: better error code for this case.
    }

    if(peerID) {
        check(filter->peerID.data==NULL); // Note sure that's illegal, but it's fishy
        filter->callbacks->load_session_data(filter->callback_ctx, *peerID, &filter->resumableSession);
        SSLFreeBuffer(&filter->peerID);
        SSLCopyBuffer(peerID, &filter->peerID);
    } else {
        SSLFreeBuffer(&filter->peerID);
    }
    return SSLAdvanceHandshake(SSL_HdskHelloRequest, filter);
}
Ejemplo n.º 10
0
/*
 * Wrapper for HashReference.close. Tolerates NULL state and frees it if it's
 * there.
 */
OSStatus CloseHash(const HashReference *ref, SSLBuffer *state, SSLContext *ctx)
{
	OSStatus serr;

	if(state->data == NULL) {
		return noErr;
	}
	serr = ref->close(state, ctx);
	if(serr) {
		return serr;
	}
	return SSLFreeBuffer(state, ctx);
}
Ejemplo n.º 11
0
static int
tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey, SSLBuffer *sessionData)
{
    SSLContext *myCtx = (SSLContext *)ctx;
    int err = errSSLSessionNotFound;

    SSLFreeBuffer(&myCtx->resumableSession);
    if(myCtx->cache) {
        err = tls_cache_load_session_data(myCtx->cache, &sessionKey, &myCtx->resumableSession);
    }
    sslDebugLog("%p, key len=%zd, data len=%zd, err=%d\n", ctx, sessionKey.length, sessionData->length, err);
    *sessionData = myCtx->resumableSession;

    return err;
}
Ejemplo n.º 12
0
/*
 * Get raw key bits from an RSA public key.
 */
OSStatus sslGetPubKeyBits(
	SSLContext			*ctx,			// Currently unused.
	SSLPubKey           *pubKey,
	SSLBuffer			*modulus,		// data mallocd and RETURNED
	SSLBuffer			*exponent)		// data mallocd and RETURNED
{
	OSStatus status;

	status = sslGiantToBuffer(ctx, &pubKey->rsaKey.n.g, modulus);
	if(status)
		return status;

	status = sslGiantToBuffer(ctx, &pubKey->rsaKey.e.g, exponent);
	if(status) {
		SSLFreeBuffer(modulus, ctx);
		return status;
	}

	return status;
}
Ejemplo n.º 13
0
int
SSLProcessCertificateStatus(tls_buffer message, tls_handshake_t ctx)
{
    uint8_t status_type;
    uint8_t *p = message.data;
    assert(!ctx->isServer);

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

    status_type = *p++;

    if(status_type!=SSL_CST_Ocsp) {
        return noErr;
    }

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

    size_t OCSPResponseLen = SSLDecodeSize(p, 3); p+=3;

    if(OCSPResponseLen==0) {
        sslErrorLog("SSLProcessCertificateStatus: message length decode error (3)\n");
        return errSSLProtocol;
    }

    if(OCSPResponseLen+4 != message.length) {
        sslErrorLog("SSLProcessCertificateStatus: message length decode error (4)\n");
        return errSSLProtocol;
    }

    ctx->ocsp_response_received = true;

    SSLFreeBuffer(&ctx->ocsp_response);
    return SSLCopyBufferFromData(p, OCSPResponseLen, &ctx->ocsp_response);
}
Ejemplo n.º 14
0
static OSStatus sslGiantToBuffer(
	SSLContext			*ctx,			// Currently unused.
	giant g,
	SSLBuffer *buffer)
{
	gi_uint8 *chars;
	gi_uint16 ioLen;
	gi_uint16 zeroCount;
	GIReturn giReturn;
	OSStatus status;

	ioLen = serializeGiantBytes(g);
	status = SSLAllocBuffer(buffer, ioLen, ctx);
	if (status)
		return status;
	chars = buffer->data;

	/* Serialize the giant g into chars. */
	giReturn = serializeGiant(g, chars, &ioLen);
	if(giReturn) {
		SSLFreeBuffer(buffer, ctx);
		return giReturnToSSL(giReturn);
	}

	/* Trim off leading zeroes (but leave one zero if that's all there is). */
	for (zeroCount = 0; zeroCount < (ioLen - 1); ++zeroCount)
		if (chars[zeroCount])
			break;

	if (zeroCount > 0) {
		buffer->length = ioLen - zeroCount;
		memmove(chars, chars + zeroCount, buffer->length);
	}

	return status;
}
Ejemplo n.º 15
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;
}
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 {
Ejemplo n.º 17
0
/* replace existing mSessionData */
static OSStatus SessionCacheEntrySetSessionData(SessionCacheEntry *entry,
	const SSLBuffer *data)
{
	SSLFreeBuffer(&entry->mSessionData, NULL);
	return SSLCopyBuffer(data, &entry->mSessionData);
}
Ejemplo n.º 18
0
void
tls_handshake_destroy(tls_handshake_t filter)
{
    tls_metric_destroyed(filter);

    /* Free the last handshake message flight */
    SSLResetFlight(filter);

    CloseHash(&SSLHashSHA1, &filter->shaState);
    CloseHash(&SSLHashMD5,  &filter->md5State);
    CloseHash(&SSLHashSHA256,  &filter->sha256State);
    CloseHash(&SSLHashSHA384,  &filter->sha384State);
    CloseHash(&SSLHashSHA512,  &filter->sha512State);

    sslFreePubKey(&filter->peerPubKey);
    sslFreePubKey(&filter->rsaEncryptPubKey);

    SSLFreeBuffer(&filter->fragmentedMessageCache);
    SSLFreeBuffer(&filter->peerID);
    SSLFreeBuffer(&filter->proposedSessionID);
    SSLFreeBuffer(&filter->sessionID);
    SSLFreeBuffer(&filter->sessionTicket);
    SSLFreeBuffer(&filter->externalSessionTicket);
    SSLFreeBuffer(&filter->preMasterSecret);
    SSLFreeBuffer(&filter->dhPeerPublic);
	SSLFreeBuffer(&filter->ecdhPeerPublic);
    SSLFreeBuffer(&filter->npnOwnData);
    SSLFreeBuffer(&filter->npnPeerData);
    SSLFreeBuffer(&filter->alpnOwnData);
    SSLFreeBuffer(&filter->alpnPeerData);
    SSLFreeBuffer(&filter->ownVerifyData);
    SSLFreeBuffer(&filter->peerVerifyData);
    SSLFreeBuffer(&filter->pskIdentity);
    SSLFreeBuffer(&filter->pskSharedSecret);
    SSLFreeBuffer(&filter->peerDomainName);
    SSLFreeBuffer(&filter->ocsp_response);
    SSLFreeBuffer(&filter->ocsp_request_extensions);
    tls_free_buffer_list(filter->ocsp_responder_id_list);
    tls_free_buffer_list(filter->sct_list);

    sslFree(filter->userAgent);
    sslFree(filter->enabledCipherSuites);
    sslFree(filter->requestedCipherSuites);
    sslFree(filter->ecdhCurves);
    sslFree(filter->peerSigAlgs);
    sslFree(filter->localSigAlgs);
    sslFree(filter->clientAuthTypes);
    sslFree(filter->ecdhContext._full);
    sslFree(filter->dhParams.gp);
    sslFree(filter->dhContext._full);
    sslFree(filter->requested_ecdh_curves);

    if(filter->signingPrivKeyRef)
        tls_private_key_destroy(filter->signingPrivKeyRef);
    SSLFreeCertificates(filter->localCert);

    SSLFreeCertificates(filter->peerCert);
    if(!filter->isServer) {
        SSLFreeDNList(filter->acceptableDNList);
    }

    free(filter);
}
Ejemplo n.º 19
0
int
tls_handshake_set_alpn_data(tls_handshake_t filter, tls_buffer alpnData)
{
    SSLFreeBuffer(&filter->alpnOwnData);
    return SSLCopyBuffer(&alpnData, &filter->alpnOwnData);
}