]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/clxutils/sslEAP/ringBufferThreads.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / sslEAP / ringBufferThreads.cpp
diff --git a/SecurityTests/clxutils/sslEAP/ringBufferThreads.cpp b/SecurityTests/clxutils/sslEAP/ringBufferThreads.cpp
new file mode 100644 (file)
index 0000000..294efde
--- /dev/null
@@ -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 <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  /* 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;
+}