ringBufferThreads.cpp [plain text]
#include "ringBufferThreads.h"
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <strings.h>
#include <clAppUtils/sslAppUtils.h>
#include <utilLib/common.h>
#include <CommonCrypto/CommonDigest.h>
#define LOG_TOP_IO 0
#if LOG_TOP_IO
static void logWrite(
char *who,
size_t written)
{
pthread_mutex_lock(&printfMutex);
printf("+++ %s wrote %4lu bytes\n", who, (unsigned long)written);
pthread_mutex_unlock(&printfMutex);
}
static void logRead(
char *who,
size_t bytesRead)
{
pthread_mutex_lock(&printfMutex);
printf("+++ %s read %4lu bytes\n", who, (unsigned long)bytesRead);
pthread_mutex_unlock(&printfMutex);
}
#else
#define logWrite(who, w)
#define logRead(who, r)
#endif
static void sslMasterSecretFunction(
SSLContextRef ctx,
const void *arg,
void *secret,
size_t *secretLength)
{
RingBufferArgs *sslArgs = (RingBufferArgs *)arg;
if(*secretLength < SSL_MASTER_SECRET_SIZE) {
printf("**Hey! insufficient space for master secret!\n");
return;
}
unsigned char r[SSL_CLIENT_SRVR_RAND_SIZE];
size_t rSize = SSL_CLIENT_SRVR_RAND_SIZE;
CC_SHA512_CTX digestCtx;
CC_SHA384_Init(&digestCtx);
SSLInternalServerRandom(ctx, r, &rSize);
CC_SHA384_Update(&digestCtx, r, rSize);
SSLInternalClientRandom(ctx, r, &rSize);
CC_SHA384_Update(&digestCtx, r, rSize);
CC_SHA384_Update(&digestCtx, sslArgs->sharedSecret, SHARED_SECRET_SIZE);
CC_SHA384_Final((unsigned char *)secret, &digestCtx);
*secretLength = CC_SHA384_DIGEST_LENGTH;
}
void *rbClientThread(void *arg)
{
RingBufferArgs *sslArgs = (RingBufferArgs *)arg;
OSStatus ortn;
SSLContextRef ctx = NULL;
RingBuffers ringBufs = {sslArgs->ringRead, sslArgs->ringWrite};
char sessionID[MAX_SESSION_ID_LENGTH];
size_t sessionIDLen = MAX_SESSION_ID_LENGTH;
unsigned toMove;
unsigned thisMove;
ortn = SSLNewContext(false, &ctx);
if(ortn) {
printSslErrStr("SSLNewContext", ortn);
goto cleanup;
}
ortn = SSLSetIOFuncs(ctx, ringReadFunc, ringWriteFunc);
if(ortn) {
printSslErrStr("SSLSetIOFuncs", ortn);
goto cleanup;
}
ortn = SSLSetConnection(ctx, (SSLConnectionRef)&ringBufs);
if(ortn) {
printSslErrStr("SSLSetConnection", ortn);
goto cleanup;
}
ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocol2, false);
if(ortn) {
printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
goto cleanup;
}
ortn = SSLInternalSetMasterSecretFunction(ctx, sslMasterSecretFunction, sslArgs);
if(ortn) {
printSslErrStr("SSLInternalSetMasterSecretFunction", ortn);
goto cleanup;
}
ortn = SSLInternalSetSessionTicket(ctx, sslArgs->sessionTicket,
sslArgs->sessionTicketLen);
if(ortn) {
printSslErrStr("SSLInternalSetSessionTicket", ortn);
goto cleanup;
}
if(sslArgs->trustedRoots) {
ortn = SSLSetTrustedRoots(ctx, sslArgs->trustedRoots, true);
if(ortn) {
printSslErrStr("SSLSetTrustedRoots", ortn);
goto cleanup;
}
}
if(sslArgs->hostName) {
ortn = SSLSetPeerDomainName(ctx, sslArgs->hostName, strlen(sslArgs->hostName));
if(ortn) {
printSslErrStr("SSLSetPeerDomainName", ortn);
goto cleanup;
}
}
sslArgs->iAmReady = true;
while(!(*sslArgs->goFlag)) {
if(*sslArgs->abortFlag) {
goto cleanup;
}
}
sslArgs->startHandshake = CFAbsoluteTimeGetCurrent();
do {
ortn = SSLHandshake(ctx);
if(*sslArgs->abortFlag) {
goto cleanup;
}
} while (ortn == errSSLWouldBlock);
if(ortn) {
printSslErrStr("SSLHandshake", ortn);
goto cleanup;
}
SSLGetNegotiatedCipher(ctx, &sslArgs->negotiatedCipher);
SSLGetNegotiatedProtocolVersion(ctx, &sslArgs->negotiatedProt);
ortn = SSLGetResumableSessionInfo(ctx, &sslArgs->sessionWasResumed, sessionID, &sessionIDLen);
if(ortn) {
printSslErrStr("SSLGetResumableSessionInfo", ortn);
goto cleanup;
}
sslArgs->startData = CFAbsoluteTimeGetCurrent();
toMove = sslArgs->xferSize;
if(toMove == 0) {
sslArgs->endData = sslArgs->startData;
goto cleanup;
}
do {
thisMove = sslArgs->chunkSize;
if(thisMove > toMove) {
thisMove = toMove;
}
size_t moved;
ortn = SSLWrite(ctx, sslArgs->xferBuf, thisMove, &moved);
if(ortn) {
printSslErrStr("SSLWrite", ortn);
goto cleanup;
}
logWrite("client", moved);
toMove -= moved;
if(*sslArgs->abortFlag) {
goto cleanup;
}
} while(toMove);
sslArgs->endData = CFAbsoluteTimeGetCurrent();
cleanup:
if(ortn) {
*sslArgs->abortFlag = true;
}
if(*sslArgs->abortFlag && sslArgs->pauseOnError) {
testError(CSSM_FALSE);
}
if(ctx) {
SSLClose(ctx);
SSLDisposeContext(ctx);
}
if(ortn) {
printf("***Client thread returning %lu\n", (unsigned long)ortn);
}
pthread_exit((void*)ortn);
return (void *)ortn;
}
OSStatus rbServerThread(RingBufferArgs *sslArgs)
{
OSStatus ortn;
SSLContextRef ctx = NULL;
RingBuffers ringBufs = {sslArgs->ringRead, sslArgs->ringWrite};
char sessionID[MAX_SESSION_ID_LENGTH];
size_t sessionIDLen = MAX_SESSION_ID_LENGTH;
unsigned toMove;
unsigned thisMove;
ortn = SSLNewContext(true, &ctx);
if(ortn) {
printSslErrStr("SSLNewContext", ortn);
goto cleanup;
}
ortn = SSLSetIOFuncs(ctx, ringReadFunc, ringWriteFunc);
if(ortn) {
printSslErrStr("SSLSetIOFuncs", ortn);
goto cleanup;
}
ortn = SSLSetConnection(ctx, (SSLConnectionRef)&ringBufs);
if(ortn) {
printSslErrStr("SSLSetConnection", ortn);
goto cleanup;
}
if(sslArgs->setMasterSecret) {
ortn = SSLInternalSetMasterSecretFunction(ctx, sslMasterSecretFunction, sslArgs);
if(ortn) {
printSslErrStr("SSLInternalSetMasterSecretFunction", ortn);
goto cleanup;
}
}
if(sslArgs->idArray) {
ortn = SSLSetCertificate(ctx, sslArgs->idArray);
if(ortn) {
printSslErrStr("SSLSetCertificate", ortn);
goto cleanup;
}
}
if(sslArgs->trustedRoots) {
ortn = SSLSetTrustedRoots(ctx, sslArgs->trustedRoots, true);
if(ortn) {
printSslErrStr("SSLSetTrustedRoots", ortn);
goto cleanup;
}
}
sslArgs->iAmReady = true;
while(!(*sslArgs->goFlag)) {
if(*sslArgs->abortFlag) {
goto cleanup;
}
}
sslArgs->startHandshake = CFAbsoluteTimeGetCurrent();
do {
ortn = SSLHandshake(ctx);
if(*sslArgs->abortFlag) {
goto cleanup;
}
} while (ortn == errSSLWouldBlock);
if(ortn) {
printSslErrStr("SSLHandshake", ortn);
goto cleanup;
}
SSLGetNegotiatedCipher(ctx, &sslArgs->negotiatedCipher);
SSLGetNegotiatedProtocolVersion(ctx, &sslArgs->negotiatedProt);
ortn = SSLGetResumableSessionInfo(ctx, &sslArgs->sessionWasResumed, sessionID, &sessionIDLen);
if(ortn) {
printSslErrStr("SSLGetResumableSessionInfo", ortn);
goto cleanup;
}
sslArgs->startData = CFAbsoluteTimeGetCurrent();
toMove = sslArgs->xferSize;
if(toMove == 0) {
sslArgs->endData = sslArgs->startData;
goto cleanup;
}
do {
thisMove = sslArgs->xferSize;
if(thisMove > toMove) {
thisMove = toMove;
}
size_t moved;
ortn = SSLRead(ctx, sslArgs->xferBuf, thisMove, &moved);
switch(ortn) {
case noErr:
break;
case errSSLWouldBlock:
ortn = noErr;
break;
default:
break;
}
if(ortn) {
printSslErrStr("SSLRead", ortn);
goto cleanup;
}
logRead("server", moved);
toMove -= moved;
if(*sslArgs->abortFlag) {
goto cleanup;
}
} while(toMove);
sslArgs->endData = CFAbsoluteTimeGetCurrent();
cleanup:
if(ortn) {
*sslArgs->abortFlag = true;
}
if(*sslArgs->abortFlag && sslArgs->pauseOnError) {
testError(CSSM_FALSE);
}
if(ctx) {
SSLClose(ctx);
SSLDisposeContext(ctx);
}
if(ortn) {
printf("***Server thread returning %lu\n", (unsigned long)ortn);
}
return ortn;
}