X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/sslHdshakeTime/sslHdshakeTime.cpp diff --git a/SecurityTests/clxutils/sslHdshakeTime/sslHdshakeTime.cpp b/SecurityTests/clxutils/sslHdshakeTime/sslHdshakeTime.cpp new file mode 100644 index 00000000..6a4d714e --- /dev/null +++ b/SecurityTests/clxutils/sslHdshakeTime/sslHdshakeTime.cpp @@ -0,0 +1,479 @@ +/* + * Measure performance of SecureTransport handshake + * + * Written by Doug Mitchell. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* default - run both server and client on this machine, port 1200 */ +#define HOST_DEF "localhost" +#define PORT_DEF 1200 + +/* default keychain */ +#define DEFAULT_KC "localcert" + +#define DH_PARAM_FILE "dhParams_1024.der" + +#define GET_MSG "GET / HTTP/1.0\r\n\r\n" + +static void usage(char **argv) +{ + printf("Usage: %s s[erver]|c[lient] loops [option ...]\n", argv[0]); + printf("Options:\n"); + printf(" -h hostname (default = %s)\n", HOST_DEF); + printf(" -p port (default = %d)\n", PORT_DEF); + printf(" -k keychain (default = %s)\n", DEFAULT_KC); + printf(" -c cipher (default = RSA/RC4; server side only)\n"); + printf(" ciphers: r=RSA/RC4; d=RSA/DES; D=RSA/3DES; h=DHA/RC4; " + "H=DH/DSS/DES\n"); + printf(" -v version (t|2|3 default = t(TLS1); server side only)\n"); + printf(" -w password (unlock server keychain with password)\n"); + printf(" -a (enable client authentication)\n"); + printf(" -r (resumable session enabled; default is disabled)\n"); + printf(" -n (No client side anchor specification; root is in system KC)\n"); + printf(" -d (disable cert verify)\n"); + printf(" -o (Allow hostname spoofing)\n"); + printf(" -g Send GET msg (needs for talking to real servers)\n"); + printf(" -V (verbose)\n"); + exit(1); +} + +#include + +void sigpipe(int sig) +{ + fflush(stdin); + printf("***SIGPIPE***\n"); +} + +int main(int argc, char **argv) +{ + /* user-spec'd variables */ + unsigned loops; + char *kcName = DEFAULT_KC; + int port = PORT_DEF; + char *hostName = HOST_DEF; + SSLCipherSuite cipherSuite = SSL_RSA_WITH_RC4_128_SHA; + SSLProtocol prot = kTLSProtocol1Only; + char password[200]; + bool clientAuthEnable = false; + bool isServer = false; + bool diffieHellman = false; + bool verbose = false; + bool resumeEnable = false; + bool setClientAnchor = true; + bool certVerifyEnable = true; + bool checkHostName = true; + bool sendGet = false; + + otSocket listenSock = 0; // for server only + CFArrayRef myCerts = NULL; + + signal(SIGPIPE, sigpipe); + if(argc < 3) { + usage(argv); + } + password[0] = 0; + switch(argv[1][0]) { + case 's': + isServer = true; + break; + case 'c': + isServer = false; + break; + default: + usage(argv); + } + loops = atoi(argv[2]); + if(loops == 0) { + usage(argv); + } + + extern int optind; + extern char *optarg; + int arg; + optind = 3; + while ((arg = getopt(argc, argv, "h:p:k:x:c:v:w:b:aVrndog")) != -1) { + switch (arg) { + case 'h': + hostName = optarg; + break; + case 'p': + port = atoi(optarg); + break; + case 'k': + kcName = 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; + 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 'a': + clientAuthEnable = true; + break; + case 'V': + verbose = true; + break; + case 'r': + resumeEnable = true; + break; + case 'n': + setClientAnchor = false; + break; + case 'd': + certVerifyEnable = false; + break; + case 'o': + checkHostName = false; + break; + case 'g': + sendGet = true; + break; + default: + usage(argv); + } + } + + /* gather Diffie-Hellman params from cwd */ + if(JAGUAR_BUILD && diffieHellman) { + printf("***SOrry, DIffie Hellman not available in this config.\n"); + exit(1); + } + 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; + if(isServer || clientAuthEnable || setClientAnchor) { + 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 %lu\n", ortn); + /* oh well */ + } + } + } + + /* just do this once */ + if(clientAuthEnable || isServer || setClientAnchor) { + myCerts = sslKcRefToCertArray(certKc, CSSM_FALSE, CSSM_TRUE, NULL); + if(myCerts == NULL) { + exit(1); + } + } + + /* server sets up listen port just once */ + if(isServer) { + printf("...listening for client connection on port %d\n", port); + ortn = ListenForClients(port, 0, &listenSock); + if(ortn) { + printf("...error establishing a listen socket. Aborting.\n"); + exit(1); + } + } + + CFAbsoluteTime setupTotal = 0; + CFAbsoluteTime handShakeTotal = 0; + + for(unsigned loop=0; loop