X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/sslEAP/ringBufferThreads.cpp diff --git a/SecurityTests/clxutils/sslEAP/ringBufferThreads.cpp b/SecurityTests/clxutils/sslEAP/ringBufferThreads.cpp new file mode 100644 index 00000000..294efde1 --- /dev/null +++ b/SecurityTests/clxutils/sslEAP/ringBufferThreads.cpp @@ -0,0 +1,359 @@ +/* + * ringBufferThreads.cpp - SecureTransport client and server thread + * routines which use ringBufferIo for I/O (no sockets). + * + * Customized for EAP-FAST testing; uses SSLInternalSetMasterSecretFunction() + * and SSLInternalSetSessionTicket(). + */ + +#include "ringBufferThreads.h" +#include +#include +#include +#include +#include +#include +#include + +#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 /* LOG_TOP_IO */ +#define logWrite(who, w) +#define logRead(who, r) +#endif /* LOG_TOP_IO */ + +/* + * Callback from ST to calculate master secret. + * We do a poor person's T_PRF(), taking the hash of: + * + * serverRandom | clientRandom | sharedSecret + * + * ...to prove that both sides can come up with a master secret + * independently, using both sides' random values and the shared secret + * supplied by the app. + * + * We happen to have a digest that produces the required number + * of bytes (48)... + */ +static void sslMasterSecretFunction( + SSLContextRef ctx, + const void *arg, /* actually a RingBufferArgs */ + void *secret, /* mallocd by caller, SSL_MASTER_SECRET_SIZE */ + size_t *secretLength) /* in/out */ +{ + 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; +} + +/* client thread - handshake and write some data */ +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; + } + /* EAP is TLS only - disable the SSLv2-capable handshake */ + 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; + } + } + + /* tell main thread we're ready; wait for sync flag */ + sslArgs->iAmReady = true; + while(!(*sslArgs->goFlag)) { + if(*sslArgs->abortFlag) { + goto cleanup; + } + } + + /* GO handshake */ + 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; + } + + /* GO data xfer */ + do { + thisMove = sslArgs->chunkSize; + if(thisMove > toMove) { + thisMove = toMove; + } + size_t moved; + ortn = SSLWrite(ctx, sslArgs->xferBuf, thisMove, &moved); + /* should never fail - implemented as blocking */ + 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) { + /* abort for any reason - freeze! */ + testError(CSSM_FALSE); + } + if(ctx) { + SSLClose(ctx); + SSLDisposeContext(ctx); + } + if(ortn) { + printf("***Client thread returning %lu\n", (unsigned long)ortn); + } + pthread_exit((void*)ortn); + /* NOT REACHED */ + return (void *)ortn; + +} + +/* server function - like clientThread except it runs from the main thread */ +/* handshake and read some data */ +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; + } + } + + /* tell client thread we're ready; wait for sync flag */ + sslArgs->iAmReady = true; + while(!(*sslArgs->goFlag)) { + if(*sslArgs->abortFlag) { + goto cleanup; + } + } + + /* GO handshake */ + 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; + } + + /* GO data xfer */ + 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: + /* cool, try again */ + 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) { + /* abort for any reason - freeze! */ + testError(CSSM_FALSE); + } + if(ctx) { + SSLClose(ctx); + SSLDisposeContext(ctx); + } + if(ortn) { + printf("***Server thread returning %lu\n", (unsigned long)ortn); + } + return ortn; +}