int sslVerifyProtVers( char *whichSide, // "client" or "server" SSLProtocol expectProt, SSLProtocol gotProt) { if(expectProt == SSL_PROTOCOL_IGNORE) { /* app says "don't bopther checking" */ return 0; } if(expectProt == gotProt) { return 0; } printf("***%s: Expected return %s; got %s\n", whichSide, sslGetProtocolVersionString(expectProt), sslGetProtocolVersionString(gotProt)); return 1; }
void sslShowResult( char *whichSide, // "client" or "server" SslAppTestParams *params) { printf("%s status:\n", whichSide); if(params->acceptedProts) { printf(" Allowed SSL versions : %s\n", params->acceptedProts); } else { printf(" Attempted SSL version : %s\n", sslGetProtocolVersionString(params->tryVersion)); } printf(" Result : %s\n", sslGetSSLErrString(params->ortn)); printf(" Negotiated SSL version : %s\n", sslGetProtocolVersionString(params->negVersion)); printf(" Negotiated CipherSuite : %s\n", sslGetCipherSuiteString(params->negCipher)); if(params->certState != kSSLClientCertNone) { printf(" Client Cert State : %s\n", sslGetClientCertStateString(params->certState)); } }
static void showSSLResult( SSLProtocol tryVersion, OSStatus err, SSLProtocol negVersion, SSLCipherSuite negCipher, CFArrayRef peerCerts, CSSM_BOOL displayPeerCerts, char *fileBase) // non-NULL: write certs to file { CFIndex numPeerCerts; printf("\n"); printf(" Attempted SSL version : %s\n", sslGetProtocolVersionString(tryVersion)); printf(" Result : %s\n", sslGetSSLErrString(err)); printf(" Negotiated SSL version : %s\n", sslGetProtocolVersionString(negVersion)); printf(" Negotiated CipherSuite : %s\n", sslGetCipherSuiteString(negCipher)); if(peerCerts == NULL) { numPeerCerts = 0; } else { numPeerCerts = CFArrayGetCount(peerCerts); } printf(" Number of peer certs : %d\n", numPeerCerts); if(numPeerCerts != 0) { if(displayPeerCerts) { showPeerCerts(peerCerts, CSSM_FALSE); } if(fileBase != NULL) { writePeerCerts(peerCerts, fileBase); } } printf("\n"); }
int main(int argc, char **argv) { RingBuffer serverToClientRing; RingBuffer clientToServerRing; unsigned numBufs = DEFAULT_NUM_BUFS; unsigned bufSize = DEFAULT_BUF_SIZE; unsigned chunkSize = DEFAULT_CHUNK; unsigned char clientBuf[DEFAULT_CHUNK]; unsigned char serverBuf[DEFAULT_CHUNK]; RingBufferArgs clientArgs; RingBufferArgs serverArgs; bool abortFlag = false; pthread_t client_thread = NULL; int result; OSStatus ortn; unsigned char sessionTicket[SESSION_TICKET_SIZE]; int ourRtn = 0; CFArrayRef idArray = NULL; /* for SSLSetCertificate */ CFArrayRef anchorArray = NULL; /* trusted roots */ char *hostName = NULL; /* user-spec'd variables */ char *kcName = NULL; unsigned xferSize = DEFAULT_XFER; bool pauseOnError = false; bool runForever = false; bool skipPAC = false; extern int optind; extern char *optarg; int arg; optind = 1; while ((arg = getopt(argc, argv, "x:c:k:h:np")) != -1) { switch (arg) { case 'x': { unsigned xsize = atoi(optarg); if(xsize == 0) { runForever = true; /* and leave xferSize alone */ } else { xferSize = xsize; } break; } case 'k': kcName = optarg; break; case 'n': skipPAC = true; break; case 'h': /* mainly to test EAP session ticket and ServerName simultaneously */ hostName = optarg; break; case 'p': pauseOnError = true; break; default: usage(argv); } } if(optind != argc) { usage(argv); } /* set up ring buffers */ ringBufSetup(&serverToClientRing, "serveToClient", numBufs, bufSize); ringBufSetup(&clientToServerRing, "clientToServe", numBufs, bufSize); /* get optional server SecIdentity */ if(kcName) { SecKeychainRef kcRef = NULL; SecCertificateRef anchorCert = NULL; SecIdentityRef idRef = NULL; idArray = getSslCerts(kcName, CSSM_FALSE, /* encryptOnly */ CSSM_FALSE, /* completeCertChain */ NULL, /* anchorFile */ &kcRef); if(idArray == NULL) { printf("***Can't get signing cert from %s\n", kcName); exit(1); } idRef = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, 0); ortn = SecIdentityCopyCertificate(idRef, &anchorCert); if(ortn) { cssmPerror("SecIdentityCopyCertificate", ortn); exit(1); } anchorArray = CFArrayCreate(NULL, (const void **)&anchorCert, 1, &kCFTypeArrayCallBacks); CFRelease(kcRef); CFRelease(anchorCert); } /* set up server side */ memset(&serverArgs, 0, sizeof(serverArgs)); serverArgs.xferSize = xferSize; serverArgs.xferBuf = serverBuf; serverArgs.chunkSize = chunkSize; serverArgs.ringWrite = &serverToClientRing; serverArgs.ringRead = &clientToServerRing; serverArgs.goFlag = &clientArgs.iAmReady; serverArgs.abortFlag = &abortFlag; serverArgs.pauseOnError = pauseOnError; appGetRandomBytes(serverArgs.sharedSecret, SHARED_SECRET_SIZE); if(!skipPAC) { serverArgs.setMasterSecret = true; } serverArgs.idArray = idArray; serverArgs.trustedRoots = anchorArray; /* set up client side */ memset(&clientArgs, 0, sizeof(clientArgs)); clientArgs.xferSize = xferSize; clientArgs.xferBuf = clientBuf; clientArgs.chunkSize = chunkSize; clientArgs.ringWrite = &clientToServerRing; clientArgs.ringRead = &serverToClientRing; clientArgs.goFlag = &serverArgs.iAmReady; clientArgs.abortFlag = &abortFlag; clientArgs.pauseOnError = pauseOnError; memmove(clientArgs.sharedSecret, serverArgs.sharedSecret, SHARED_SECRET_SIZE); clientArgs.hostName = hostName; /* for now set up an easily recognizable ticket */ for(unsigned dex=0; dex<SESSION_TICKET_SIZE; dex++) { sessionTicket[dex] = dex; } clientArgs.sessionTicket = sessionTicket; clientArgs.sessionTicketLen = SESSION_TICKET_SIZE; /* client always tries setting the master secret in this test */ clientArgs.setMasterSecret = true; clientArgs.trustedRoots = anchorArray; /* fire up client thread */ result = pthread_create(&client_thread, NULL, rbClientThread, &clientArgs); if(result) { printf("***pthread_create returned %d, aborting\n", result); exit(1); } /* * And the server pseudo thread. This returns when all data has been transferred. */ ortn = rbServerThread(&serverArgs); if(abortFlag) { printf("***Test aborted.\n"); exit(1); } printf("\n"); printf("SSL Protocol Version : %s\n", sslGetProtocolVersionString(serverArgs.negotiatedProt)); printf("SSL Cipher : %s\n", sslGetCipherSuiteString(serverArgs.negotiatedCipher)); if(skipPAC) { if(clientArgs.sessionWasResumed) { printf("***skipPAC true, but client reported sessionWasResumed\n"); ourRtn = -1; } if(serverArgs.sessionWasResumed) { printf("***skipPAC true, but server reported sessionWasResumed\n"); ourRtn = -1; } if(ourRtn == 0) { printf("...PAC session attempted by client; refused by server;\n"); printf(" Normal session proceeded correctly.\n"); } } else { if(!clientArgs.sessionWasResumed) { printf("***client reported !sessionWasResumed\n"); ourRtn = -1; } if(!serverArgs.sessionWasResumed) { printf("***server reported !sessionWasResumed\n"); ourRtn = -1; } if(memcmp(clientBuf, serverBuf, DEFAULT_CHUNK)) { printf("***Data miscompare***\n"); ourRtn = -1; } if(ourRtn == 0) { printf("...PAC session resumed correctly.\n"); } } /* FIXME other stuff? */ return ourRtn; }
static void showSSLResult( SSLProtocol tryVersion, char *acceptedProts, OSStatus err, SSLProtocol negVersion, SSLCipherSuite negCipher, Boolean sessionWasResumed, unsigned char *sessionID, size_t sessionIDLength, CFArrayRef peerCerts, bool displayPeerCerts, SSLClientCertificateState certState, char *fileBase) // non-NULL: write certs to file { CFIndex numPeerCerts; printf("\n"); if(acceptedProts) { printf(" Allowed SSL versions : %s\n", acceptedProts); } else { printf(" Attempted SSL version : %s\n", sslGetProtocolVersionString(tryVersion)); } printf(" Result : %s\n", sslGetSSLErrString(err)); printf(" Negotiated SSL version : %s\n", sslGetProtocolVersionString(negVersion)); printf(" Negotiated CipherSuite : %s\n", sslGetCipherSuiteString(negCipher)); if(certState != kSSLClientCertNone) { printf(" Client Cert State : %s\n", sslGetClientCertStateString(certState)); } printf(" Resumed Session : "); if(sessionWasResumed) { for(unsigned dex=0; dex<sessionIDLength; dex++) { printf("%02X ", sessionID[dex]); if(((dex % 8) == 7) && (dex != (sessionIDLength - 1))) { printf("\n "); } } printf("\n"); } else { printf("NOT RESUMED\n"); } if(peerCerts == NULL) { numPeerCerts = 0; } else { numPeerCerts = CFArrayGetCount(peerCerts); } printf(" Number of peer certs : %lu\n", numPeerCerts); if(numPeerCerts != 0) { if(displayPeerCerts) { showPeerCerts(peerCerts, false); } if(fileBase != NULL) { writePeerCerts(peerCerts, fileBase); } } printf("\n"); }
int main(int argc, char **argv) { RingBuffer serverToClientRing; RingBuffer clientToServerRing; unsigned numBufs = DEFAULT_NUM_BUFS; unsigned bufSize = DEFAULT_BUF_SIZE; unsigned chunkSize = DEFAULT_CHUNK; unsigned char clientBuf[DEFAULT_CHUNK]; unsigned char serverBuf[DEFAULT_CHUNK]; CFArrayRef idArray; /* for SSLSetCertificate */ CFArrayRef anchorArray; /* trusted roots */ SslRingBufferArgs clientArgs; SslRingBufferArgs serverArgs; SecKeychainRef kcRef = NULL; SecCertificateRef anchorCert = NULL; SecIdentityRef idRef = NULL; bool abortFlag = false; pthread_t client_thread = NULL; int result; bool diffieHellman = true; /* FIXME needs work */ OSStatus ortn; /* user-spec'd variables */ char *kcName = DEFAULT_KC; unsigned xferSize = DEFAULT_XFER; SSLCipherSuite cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA; SSLProtocol prot = kTLSProtocol1; char password[200]; bool clientAuthEnable = false; bool pauseOnError = false; bool runForever = false; bool mallocPause = false; password[0] = 0; extern int optind; extern char *optarg; int arg; optind = 1; while ((arg = getopt(argc, argv, "k:x:c:v:w:aBpm")) != -1) { switch (arg) { case 'k': kcName = optarg; break; case 'x': { unsigned xsize = atoi(optarg); if(xsize == 0) { runForever = true; /* and leave xferSize alone */ } else { xferSize = xsize; } break; } case 'c': switch(optarg[0]) { case 'a': cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA; break; case 'r': cipherSuite = SSL_RSA_WITH_RC4_128_SHA; break; case 'd': cipherSuite = SSL_RSA_WITH_DES_CBC_SHA; break; case 'D': cipherSuite = SSL_RSA_WITH_3DES_EDE_CBC_SHA; break; case 'h': cipherSuite = SSL_DH_anon_WITH_RC4_128_MD5; diffieHellman = true; break; case 'H': cipherSuite = SSL_DHE_DSS_WITH_DES_CBC_SHA; diffieHellman = true; break; case 'A': cipherSuite = TLS_RSA_WITH_AES_256_CBC_SHA; break; default: usage(argv); } break; case 'v': switch(optarg[0]) { case 't': prot = kTLSProtocol1; break; case '2': prot = kSSLProtocol2; break; case '3': prot = kSSLProtocol3; break; default: usage(argv); } break; case 'w': strcpy(password, optarg); break; case 'a': clientAuthEnable = true; break; case 'p': pauseOnError = true; break; case 'm': mallocPause = true; break; default: usage(argv); } } if(optind != argc) { usage(argv); } /* set up ring buffers */ ringBufSetup(&serverToClientRing, "serveToClient", numBufs, bufSize); ringBufSetup(&clientToServerRing, "clientToServe", numBufs, bufSize); /* get server SecIdentity */ idArray = getSslCerts(kcName, CSSM_FALSE, /* encryptOnly */ CSSM_FALSE, /* completeCertChain */ NULL, /* anchorFile */ &kcRef); if(idArray == NULL) { printf("***Can't get signing cert from %s\n", kcName); exit(1); } idRef = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, 0); ortn = SecIdentityCopyCertificate(idRef, &anchorCert); if(ortn) { cssmPerror("SecIdentityCopyCertificate", ortn); exit(1); } anchorArray = CFArrayCreate(NULL, (const void **)&anchorCert, 1, &kCFTypeArrayCallBacks); /* unlock keychain? */ if(password[0]) { ortn = SecKeychainUnlock(kcRef, strlen(password), password, true); if(ortn) { cssmPerror("SecKeychainUnlock", ortn); /* oh well */ } } CFRelease(kcRef); if(mallocPause) { fpurge(stdin); printf("Pausing for MallocDebug setup. CR to proceed: "); getchar(); } /* set up server side */ memset(&serverArgs, 0, sizeof(serverArgs)); serverArgs.idArray = idArray; serverArgs.trustedRoots = anchorArray; serverArgs.xferSize = xferSize; serverArgs.xferBuf = serverBuf; serverArgs.chunkSize = chunkSize; serverArgs.runForever = runForever; serverArgs.cipherSuite = cipherSuite; serverArgs.prot = prot; serverArgs.ringWrite = &serverToClientRing; serverArgs.ringRead = &clientToServerRing; serverArgs.goFlag = &clientArgs.iAmReady; serverArgs.abortFlag = &abortFlag; serverArgs.pauseOnError = pauseOnError; /* set up client side */ memset(&clientArgs, 0, sizeof(clientArgs)); clientArgs.idArray = NULL; /* until we do client auth */ clientArgs.trustedRoots = anchorArray; clientArgs.xferSize = xferSize; clientArgs.xferBuf = clientBuf; clientArgs.chunkSize = chunkSize; clientArgs.runForever = runForever; clientArgs.cipherSuite = cipherSuite; clientArgs.prot = prot; clientArgs.ringWrite = &clientToServerRing; clientArgs.ringRead = &serverToClientRing; clientArgs.goFlag = &serverArgs.iAmReady; clientArgs.abortFlag = &abortFlag; clientArgs.pauseOnError = pauseOnError; /* fire up client thread */ result = pthread_create(&client_thread, NULL, sslRbClientThread, &clientArgs); if(result) { printf("***pthread_create returned %d, aborting\n", result); exit(1); } /* * And the server pseudo thread. This returns when all data has been transferred. */ ortn = sslRbServerThread(&serverArgs); if(abortFlag) { printf("***Test aborted.\n"); exit(1); } printf("\n"); if(mallocPause) { fpurge(stdin); printf("End of test. Pausing for MallocDebug analysis. CR to proceed: "); getchar(); } printf("SSL Protocol Version : %s\n", sslGetProtocolVersionString(serverArgs.negotiatedProt)); printf("SSL Cipher : %s\n", sslGetCipherSuiteString(serverArgs.negotiatedCipher)); printf("SSL Handshake : %f s\n", serverArgs.startData - serverArgs.startHandshake); printf("Data Transfer : %u bytes in %f s\n", (unsigned)xferSize, serverArgs.endData - serverArgs.startHandshake); printf(" : %.1f Kbytes/s\n", xferSize / (serverArgs.endData - serverArgs.startHandshake) / 1024.0); return 0; }
int main(int argc, char **argv) { /* user-spec'd variables */ const char *kcName = DEFAULT_KC; unsigned xferSize = XFERSIZE_DEF; int port = PORT_DEF; const char *hostName = HOST_DEF; SSLCipherSuite cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA; SSLProtocol prot = kTLSProtocol1Only; char password[200]; bool clientAuthEnable = false; bool isServer = false; unsigned bufSize = BUFSIZE; bool diffieHellman = false; int nonBlocking = 0; if(argc < 2) { usage(argv); } password[0] = 0; switch(argv[1][0]) { case 's': isServer = true; break; case 'c': isServer = false; break; default: usage(argv); } extern int optind; extern char *optarg; int arg; optind = 2; while ((arg = getopt(argc, argv, "h:p:k:x:c:v:w:b:aB")) != -1) { switch (arg) { case 'h': hostName = optarg; break; case 'p': port = atoi(optarg); break; case 'k': kcName = optarg; break; case 'x': xferSize = atoi(optarg); break; case 'c': if(!isServer) { printf("***Specify cipherSuite on server side.\n"); exit(1); } switch(optarg[0]) { case 'r': cipherSuite = SSL_RSA_WITH_RC4_128_SHA; break; case 'd': cipherSuite = SSL_RSA_WITH_DES_CBC_SHA; break; case 'D': cipherSuite = SSL_RSA_WITH_3DES_EDE_CBC_SHA; break; case 'h': cipherSuite = SSL_DH_anon_WITH_RC4_128_MD5; diffieHellman = true; break; case 'H': cipherSuite = SSL_DHE_DSS_WITH_DES_CBC_SHA; diffieHellman = true; break; case 'A': cipherSuite = TLS_RSA_WITH_AES_256_CBC_SHA; break; default: usage(argv); } break; case 'v': if(!isServer) { printf("***Specify protocol on server side.\n"); exit(1); } switch(optarg[0]) { case 't': prot = kTLSProtocol1Only; break; case '2': prot = kSSLProtocol2; break; case '3': prot = kSSLProtocol3Only; break; default: usage(argv); } break; case 'w': strcpy(password, optarg); break; case 'b': bufSize = atoi(optarg); break; case 'a': clientAuthEnable = true; break; case 'B': nonBlocking = 1; break; default: usage(argv); } } /* per-transfer buffer - make it random for server */ char *buf = (char *)malloc(bufSize); if(isServer) { Security::DevRandomGenerator rng; rng.random(buf, bufSize); } /* gather Diffie-Hellman params from cwd */ unsigned char *dhParams = NULL; unsigned dhParamsLen = 0; if(diffieHellman && isServer) { if(readFile(DH_PARAM_FILE, &dhParams, &dhParamsLen)) { printf("***Error reading Diffie-Hellman Params. Prepare to " "wait for a minute during SSL handshake.\n"); } } /* * Open keychain; both sides use the same one. */ OSStatus ortn; SecKeychainRef certKc = NULL; CFAbsoluteTime kcOpenStart = CFAbsoluteTimeGetCurrent(); ortn = SecKeychainOpen(kcName, &certKc); if(ortn) { printf("Error opening keychain %s (%d); aborting.\n", kcName, (int)ortn); exit(1); } if(password[0]) { ortn = SecKeychainUnlock(certKc, strlen(password), password, true); if(ortn) { printf("SecKeychainUnlock returned %d\n", (int)ortn); /* oh well */ } } CFAbsoluteTime kcOpenEnd = CFAbsoluteTimeGetCurrent(); otSocket peerSock = 0; otSocket listenSock = 0; // for server only PeerSpec peerId; if(isServer) { printf("...listening for client connection on port %d\n", port); ortn = ListenForClients(port, nonBlocking, &listenSock); if(ortn) { printf("...error establishing a listen socket. Aborting.\n"); exit(1); } ortn = AcceptClientConnection(listenSock, &peerSock, &peerId); if(ortn) { printf("...error listening for connection. Aborting.\n"); exit(1); } } else { printf("...connecting to host %s at port %d\n", hostName, port); ortn = MakeServerConnection(hostName, port, nonBlocking, &peerSock, &peerId); if(ortn) { printf("...error connecting to server %s. Aborting.\n", hostName); exit(1); } } /* start timing SSL setup */ CFAbsoluteTime setupStart = CFAbsoluteTimeGetCurrent(); SSLContextRef ctx; ortn = SSLNewContext(isServer, &ctx); if(ortn) { printSslErrStr("SSLNewContext", ortn); exit(1); } ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); if(ortn) { printSslErrStr("SSLSetIOFuncs", ortn); exit(1); } ortn = SSLSetConnection(ctx, (SSLConnectionRef)peerSock); if(ortn) { printSslErrStr("SSLSetConnection", ortn); exit(1); } ortn = SSLSetPeerDomainName(ctx, hostName, strlen(hostName) + 1); if(ortn) { printSslErrStr("SSLSetPeerDomainName", ortn); exit(1); } /* * Server/client specific setup. * * Client uses the same keychain as server, but it uses it for * sslAddTrustedRoots() instead of getSslCerts() and * SSLSetCertificate(). */ CFArrayRef myCerts = NULL; if(clientAuthEnable || isServer) { myCerts = sslKcRefToCertArray(certKc, CSSM_FALSE, CSSM_FALSE, NULL, NULL); if(myCerts == NULL) { exit(1); } ortn = addIdentityAsTrustedRoot(ctx, myCerts); if(ortn) { exit(1); } ortn = SSLSetCertificate(ctx, myCerts); if(ortn) { printSslErrStr("SSLSetCertificate", ortn); exit(1); } } if(isServer) { SSLAuthenticate auth; if(clientAuthEnable) { auth = kAlwaysAuthenticate; } else { auth = kNeverAuthenticate; } ortn = SSLSetClientSideAuthenticate(ctx, auth); if(ortn) { printSslErrStr("SSLSetClientSideAuthenticate", ortn); exit(1); } ortn = SSLSetEnabledCiphers(ctx, &cipherSuite, 1); if(ortn) { printSslErrStr("SSLSetEnabledCiphers", ortn); exit(1); } ortn = SSLSetProtocolVersion(ctx, prot); if(ortn) { printSslErrStr("SSLSetProtocolVersion", ortn); exit(1); } if(dhParams != NULL) { ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen); if(ortn) { printSslErrStr("SSLSetDiffieHellmanParams", ortn); exit(1); } } } else { /* client setup */ if(!clientAuthEnable) { /* We're not presenting a cert; trust the server certs */ bool foundOne; ortn = sslAddTrustedRoots(ctx, certKc, &foundOne); if(ortn) { printSslErrStr("sslAddTrustedRoots", ortn); exit(1); } } } /* * Context setup complete. Start timing handshake. */ CFAbsoluteTime hshakeStart = CFAbsoluteTimeGetCurrent(); do { ortn = SSLHandshake(ctx); } while (ortn == errSSLWouldBlock); if(ortn) { printSslErrStr("SSLHandshake", ortn); exit(1); } CFAbsoluteTime hshakeEnd = CFAbsoluteTimeGetCurrent(); /* snag these before data xfer possibly shuts down connection */ SSLProtocol negVersion; SSLCipherSuite negCipher; SSLClientCertificateState certState; // RETURNED SSLGetNegotiatedCipher(ctx, &negCipher); SSLGetNegotiatedProtocolVersion(ctx, &negVersion); SSLGetClientCertificateState(ctx, &certState); /* server sends xferSize bytes to client and shuts down */ size_t bytesMoved; CFAbsoluteTime dataStart = CFAbsoluteTimeGetCurrent(); size_t totalMoved = 0; if(isServer) { size_t bytesToGo = xferSize; bool done = false; do { size_t thisMove = bufSize; if(thisMove > bytesToGo) { thisMove = bytesToGo; } ortn = SSLWrite(ctx, buf, thisMove, &bytesMoved); switch(ortn) { case noErr: case errSSLWouldBlock: break; default: done = true; break; } bytesToGo -= bytesMoved; totalMoved += bytesMoved; if(bytesToGo == 0) { done = true; } } while(!done); if(ortn != noErr) { printSslErrStr("SSLWrite", ortn); exit(1); } } else { /* client reads until error or errSSLClosedGraceful */ bool done = false; do { ortn = SSLRead(ctx, buf, bufSize, &bytesMoved); switch(ortn) { case errSSLClosedGraceful: done = true; break; case noErr: case errSSLWouldBlock: break; default: done = true; break; } totalMoved += bytesMoved; } while(!done); if(ortn != errSSLClosedGraceful) { printSslErrStr("SSLRead", ortn); exit(1); } } /* shut down channel */ ortn = SSLClose(ctx); if(ortn) { printSslErrStr("SSLCLose", ortn); exit(1); } CFAbsoluteTime dataEnd = CFAbsoluteTimeGetCurrent(); /* how'd we do? */ printf("SSL version : %s\n", sslGetProtocolVersionString(negVersion)); printf("CipherSuite : %s\n", sslGetCipherSuiteString(negCipher)); printf("Client Cert State : %s\n", sslGetClientCertStateString(certState)); if(password[0]) { printf("keychain open/unlock : "); } else { printf("keychain open : "); } printf("%f s\n", kcOpenEnd - kcOpenStart); printf("SSLContext setup : %f s\n", hshakeStart - setupStart); printf("SSL Handshake : %f s\n", hshakeEnd - hshakeStart); printf("Data Transfer : %u bytes in %f s\n", (unsigned)totalMoved, dataEnd - dataStart); printf(" : %.1f Kbytes/s\n", totalMoved / (dataEnd - dataStart) / 1024.0); return 0; }