1/* 2 * ringBufferThreads.cpp - SecureTransport client and server thread 3 * routines which use ringBufferIo for I/O (no sockets). 4 * 5 * Customized for EAP-FAST testing; uses SSLInternalSetMasterSecretFunction() 6 * and SSLInternalSetSessionTicket(). 7 */ 8 9#include "ringBufferThreads.h" 10#include <stdlib.h> 11#include <pthread.h> 12#include <stdio.h> 13#include <strings.h> 14#include <clAppUtils/sslAppUtils.h> 15#include <utilLib/common.h> 16#include <CommonCrypto/CommonDigest.h> 17 18#define LOG_TOP_IO 0 19#if LOG_TOP_IO 20 21static void logWrite( 22 char *who, 23 size_t written) 24{ 25 pthread_mutex_lock(&printfMutex); 26 printf("+++ %s wrote %4lu bytes\n", who, (unsigned long)written); 27 pthread_mutex_unlock(&printfMutex); 28} 29 30static void logRead( 31 char *who, 32 size_t bytesRead) 33{ 34 pthread_mutex_lock(&printfMutex); 35 printf("+++ %s read %4lu bytes\n", who, (unsigned long)bytesRead); 36 pthread_mutex_unlock(&printfMutex); 37} 38 39#else /* LOG_TOP_IO */ 40#define logWrite(who, w) 41#define logRead(who, r) 42#endif /* LOG_TOP_IO */ 43 44/* 45 * Callback from ST to calculate master secret. 46 * We do a poor person's T_PRF(), taking the hash of: 47 * 48 * serverRandom | clientRandom | sharedSecret 49 * 50 * ...to prove that both sides can come up with a master secret 51 * independently, using both sides' random values and the shared secret 52 * supplied by the app. 53 * 54 * We happen to have a digest that produces the required number 55 * of bytes (48)... 56 */ 57static void sslMasterSecretFunction( 58 SSLContextRef ctx, 59 const void *arg, /* actually a RingBufferArgs */ 60 void *secret, /* mallocd by caller, SSL_MASTER_SECRET_SIZE */ 61 size_t *secretLength) /* in/out */ 62{ 63 RingBufferArgs *sslArgs = (RingBufferArgs *)arg; 64 if(*secretLength < SSL_MASTER_SECRET_SIZE) { 65 printf("**Hey! insufficient space for master secret!\n"); 66 return; 67 } 68 69 unsigned char r[SSL_CLIENT_SRVR_RAND_SIZE]; 70 size_t rSize = SSL_CLIENT_SRVR_RAND_SIZE; 71 CC_SHA512_CTX digestCtx; 72 CC_SHA384_Init(&digestCtx); 73 SSLInternalServerRandom(ctx, r, &rSize); 74 CC_SHA384_Update(&digestCtx, r, rSize); 75 SSLInternalClientRandom(ctx, r, &rSize); 76 CC_SHA384_Update(&digestCtx, r, rSize); 77 CC_SHA384_Update(&digestCtx, sslArgs->sharedSecret, SHARED_SECRET_SIZE); 78 CC_SHA384_Final((unsigned char *)secret, &digestCtx); 79 *secretLength = CC_SHA384_DIGEST_LENGTH; 80} 81 82/* client thread - handshake and write some data */ 83void *rbClientThread(void *arg) 84{ 85 RingBufferArgs *sslArgs = (RingBufferArgs *)arg; 86 OSStatus ortn; 87 SSLContextRef ctx = NULL; 88 RingBuffers ringBufs = {sslArgs->ringRead, sslArgs->ringWrite}; 89 char sessionID[MAX_SESSION_ID_LENGTH]; 90 size_t sessionIDLen = MAX_SESSION_ID_LENGTH; 91 unsigned toMove; 92 unsigned thisMove; 93 94 ortn = SSLNewContext(false, &ctx); 95 if(ortn) { 96 printSslErrStr("SSLNewContext", ortn); 97 goto cleanup; 98 } 99 ortn = SSLSetIOFuncs(ctx, ringReadFunc, ringWriteFunc); 100 if(ortn) { 101 printSslErrStr("SSLSetIOFuncs", ortn); 102 goto cleanup; 103 } 104 ortn = SSLSetConnection(ctx, (SSLConnectionRef)&ringBufs); 105 if(ortn) { 106 printSslErrStr("SSLSetConnection", ortn); 107 goto cleanup; 108 } 109 /* EAP is TLS only - disable the SSLv2-capable handshake */ 110 ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocol2, false); 111 if(ortn) { 112 printSslErrStr("SSLSetProtocolVersionEnabled", ortn); 113 goto cleanup; 114 } 115 ortn = SSLInternalSetMasterSecretFunction(ctx, sslMasterSecretFunction, sslArgs); 116 if(ortn) { 117 printSslErrStr("SSLInternalSetMasterSecretFunction", ortn); 118 goto cleanup; 119 } 120 ortn = SSLInternalSetSessionTicket(ctx, sslArgs->sessionTicket, 121 sslArgs->sessionTicketLen); 122 if(ortn) { 123 printSslErrStr("SSLInternalSetSessionTicket", ortn); 124 goto cleanup; 125 } 126 if(sslArgs->trustedRoots) { 127 ortn = SSLSetTrustedRoots(ctx, sslArgs->trustedRoots, true); 128 if(ortn) { 129 printSslErrStr("SSLSetTrustedRoots", ortn); 130 goto cleanup; 131 } 132 } 133 if(sslArgs->hostName) { 134 ortn = SSLSetPeerDomainName(ctx, sslArgs->hostName, strlen(sslArgs->hostName)); 135 if(ortn) { 136 printSslErrStr("SSLSetPeerDomainName", ortn); 137 goto cleanup; 138 } 139 } 140 141 /* tell main thread we're ready; wait for sync flag */ 142 sslArgs->iAmReady = true; 143 while(!(*sslArgs->goFlag)) { 144 if(*sslArgs->abortFlag) { 145 goto cleanup; 146 } 147 } 148 149 /* GO handshake */ 150 sslArgs->startHandshake = CFAbsoluteTimeGetCurrent(); 151 do { 152 ortn = SSLHandshake(ctx); 153 if(*sslArgs->abortFlag) { 154 goto cleanup; 155 } 156 } while (ortn == errSSLWouldBlock); 157 158 if(ortn) { 159 printSslErrStr("SSLHandshake", ortn); 160 goto cleanup; 161 } 162 163 SSLGetNegotiatedCipher(ctx, &sslArgs->negotiatedCipher); 164 SSLGetNegotiatedProtocolVersion(ctx, &sslArgs->negotiatedProt); 165 166 ortn = SSLGetResumableSessionInfo(ctx, &sslArgs->sessionWasResumed, sessionID, &sessionIDLen); 167 if(ortn) { 168 printSslErrStr("SSLGetResumableSessionInfo", ortn); 169 goto cleanup; 170 } 171 172 sslArgs->startData = CFAbsoluteTimeGetCurrent(); 173 174 toMove = sslArgs->xferSize; 175 176 if(toMove == 0) { 177 sslArgs->endData = sslArgs->startData; 178 goto cleanup; 179 } 180 181 /* GO data xfer */ 182 do { 183 thisMove = sslArgs->chunkSize; 184 if(thisMove > toMove) { 185 thisMove = toMove; 186 } 187 size_t moved; 188 ortn = SSLWrite(ctx, sslArgs->xferBuf, thisMove, &moved); 189 /* should never fail - implemented as blocking */ 190 if(ortn) { 191 printSslErrStr("SSLWrite", ortn); 192 goto cleanup; 193 } 194 logWrite("client", moved); 195 toMove -= moved; 196 if(*sslArgs->abortFlag) { 197 goto cleanup; 198 } 199 } while(toMove); 200 201 sslArgs->endData = CFAbsoluteTimeGetCurrent(); 202 203cleanup: 204 if(ortn) { 205 *sslArgs->abortFlag = true; 206 } 207 if(*sslArgs->abortFlag && sslArgs->pauseOnError) { 208 /* abort for any reason - freeze! */ 209 testError(CSSM_FALSE); 210 } 211 if(ctx) { 212 SSLClose(ctx); 213 SSLDisposeContext(ctx); 214 } 215 if(ortn) { 216 printf("***Client thread returning %lu\n", (unsigned long)ortn); 217 } 218 pthread_exit((void*)ortn); 219 /* NOT REACHED */ 220 return (void *)ortn; 221 222} 223 224/* server function - like clientThread except it runs from the main thread */ 225/* handshake and read some data */ 226OSStatus rbServerThread(RingBufferArgs *sslArgs) 227{ 228 OSStatus ortn; 229 SSLContextRef ctx = NULL; 230 RingBuffers ringBufs = {sslArgs->ringRead, sslArgs->ringWrite}; 231 char sessionID[MAX_SESSION_ID_LENGTH]; 232 size_t sessionIDLen = MAX_SESSION_ID_LENGTH; 233 unsigned toMove; 234 unsigned thisMove; 235 236 ortn = SSLNewContext(true, &ctx); 237 if(ortn) { 238 printSslErrStr("SSLNewContext", ortn); 239 goto cleanup; 240 } 241 ortn = SSLSetIOFuncs(ctx, ringReadFunc, ringWriteFunc); 242 if(ortn) { 243 printSslErrStr("SSLSetIOFuncs", ortn); 244 goto cleanup; 245 } 246 ortn = SSLSetConnection(ctx, (SSLConnectionRef)&ringBufs); 247 if(ortn) { 248 printSslErrStr("SSLSetConnection", ortn); 249 goto cleanup; 250 } 251 if(sslArgs->setMasterSecret) { 252 ortn = SSLInternalSetMasterSecretFunction(ctx, sslMasterSecretFunction, sslArgs); 253 if(ortn) { 254 printSslErrStr("SSLInternalSetMasterSecretFunction", ortn); 255 goto cleanup; 256 } 257 } 258 if(sslArgs->idArray) { 259 ortn = SSLSetCertificate(ctx, sslArgs->idArray); 260 if(ortn) { 261 printSslErrStr("SSLSetCertificate", ortn); 262 goto cleanup; 263 } 264 } 265 if(sslArgs->trustedRoots) { 266 ortn = SSLSetTrustedRoots(ctx, sslArgs->trustedRoots, true); 267 if(ortn) { 268 printSslErrStr("SSLSetTrustedRoots", ortn); 269 goto cleanup; 270 } 271 } 272 273 /* tell client thread we're ready; wait for sync flag */ 274 sslArgs->iAmReady = true; 275 while(!(*sslArgs->goFlag)) { 276 if(*sslArgs->abortFlag) { 277 goto cleanup; 278 } 279 } 280 281 /* GO handshake */ 282 sslArgs->startHandshake = CFAbsoluteTimeGetCurrent(); 283 do { 284 ortn = SSLHandshake(ctx); 285 if(*sslArgs->abortFlag) { 286 goto cleanup; 287 } 288 } while (ortn == errSSLWouldBlock); 289 290 if(ortn) { 291 printSslErrStr("SSLHandshake", ortn); 292 goto cleanup; 293 } 294 295 SSLGetNegotiatedCipher(ctx, &sslArgs->negotiatedCipher); 296 SSLGetNegotiatedProtocolVersion(ctx, &sslArgs->negotiatedProt); 297 ortn = SSLGetResumableSessionInfo(ctx, &sslArgs->sessionWasResumed, sessionID, &sessionIDLen); 298 if(ortn) { 299 printSslErrStr("SSLGetResumableSessionInfo", ortn); 300 goto cleanup; 301 } 302 303 sslArgs->startData = CFAbsoluteTimeGetCurrent(); 304 305 toMove = sslArgs->xferSize; 306 307 if(toMove == 0) { 308 sslArgs->endData = sslArgs->startData; 309 goto cleanup; 310 } 311 312 /* GO data xfer */ 313 do { 314 thisMove = sslArgs->xferSize; 315 if(thisMove > toMove) { 316 thisMove = toMove; 317 } 318 size_t moved; 319 ortn = SSLRead(ctx, sslArgs->xferBuf, thisMove, &moved); 320 switch(ortn) { 321 case noErr: 322 break; 323 case errSSLWouldBlock: 324 /* cool, try again */ 325 ortn = noErr; 326 break; 327 default: 328 break; 329 } 330 if(ortn) { 331 printSslErrStr("SSLRead", ortn); 332 goto cleanup; 333 } 334 logRead("server", moved); 335 toMove -= moved; 336 if(*sslArgs->abortFlag) { 337 goto cleanup; 338 } 339 } while(toMove); 340 341 sslArgs->endData = CFAbsoluteTimeGetCurrent(); 342 343cleanup: 344 if(ortn) { 345 *sslArgs->abortFlag = true; 346 } 347 if(*sslArgs->abortFlag && sslArgs->pauseOnError) { 348 /* abort for any reason - freeze! */ 349 testError(CSSM_FALSE); 350 } 351 if(ctx) { 352 SSLClose(ctx); 353 SSLDisposeContext(ctx); 354 } 355 if(ortn) { 356 printf("***Server thread returning %lu\n", (unsigned long)ortn); 357 } 358 return ortn; 359} 360