]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/sslThroughput/sslThroughput.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / SecurityTests / clxutils / sslThroughput / sslThroughput.cpp
1 /*
2 * Measure performance of SecureTransport - setup and sustained data
3 * throughput. Single process version, no sockets - all data transfer
4 * between client and server is via local memory shared between two
5 * threads.
6 *
7 * Written by Doug Mitchell.
8 */
9 #include <Security/SecureTransport.h>
10 #include <clAppUtils/sslAppUtils.h>
11 #include <utilLib/fileIo.h>
12 #include <utilLib/common.h>
13 #include <clAppUtils/ringBufferIo.h>
14 #include <clAppUtils/sslRingBufferThreads.h>
15
16 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21 #include <ctype.h>
22 #include <sys/param.h>
23 #include <CoreFoundation/CoreFoundation.h>
24 #include <security_utilities/devrandom.h>
25
26 #define DEFAULT_KC "localcert" /* default keychain */
27 #define DEFAULT_XFER (1024 * 1024 * 20) /* total xfer size in bytes */
28
29 /* we might make these user-tweakable */
30 #define DEFAULT_NUM_BUFS 16
31 #define DEFAULT_BUF_SIZE 2048 /* in the ring buffers */
32 #define DEFAULT_CHUNK 1024 /* bytes to write per SSLWrite() */
33
34 static void usage(char **argv)
35 {
36 printf("Usage: %s [option ...]\n", argv[0]);
37 printf("Options:\n");
38 printf(" -k keychain (default = %s)\n", DEFAULT_KC);
39 printf(" -x transferSize (default=%d; 0=forever)\n", DEFAULT_XFER);
40 printf(" -c cipher (default = RSA/AES128\n");
41 printf(" ciphers: a=RSA/AES128; r=RSA/RC4; d=RSA/DES; D=RSA/3DES;\n");
42 printf(" h=DHA/RC4; H=DH/DSS/DES; A=AES256\n");
43 printf(" -v version (t|2|3; default = t(TLS1)\n");
44 printf(" -w password (unlock server keychain with password)\n");
45 printf(" -a (enable client authentication)\n");
46 printf(" -p (pause on error)\n");
47 printf(" -m (pause for malloc debug)\n");
48 exit(1);
49 }
50
51 int main(int argc, char **argv)
52 {
53 RingBuffer serverToClientRing;
54 RingBuffer clientToServerRing;
55 unsigned numBufs = DEFAULT_NUM_BUFS;
56 unsigned bufSize = DEFAULT_BUF_SIZE;
57 unsigned chunkSize = DEFAULT_CHUNK;
58 unsigned char clientBuf[DEFAULT_CHUNK];
59 unsigned char serverBuf[DEFAULT_CHUNK];
60 CFArrayRef idArray; /* for SSLSetCertificate */
61 CFArrayRef anchorArray; /* trusted roots */
62 SslRingBufferArgs clientArgs;
63 SslRingBufferArgs serverArgs;
64 SecKeychainRef kcRef = NULL;
65 SecCertificateRef anchorCert = NULL;
66 SecIdentityRef idRef = NULL;
67 bool abortFlag = false;
68 pthread_t client_thread = NULL;
69 int result;
70 bool diffieHellman = true; /* FIXME needs work */
71 OSStatus ortn;
72
73 /* user-spec'd variables */
74 char *kcName = DEFAULT_KC;
75 unsigned xferSize = DEFAULT_XFER;
76 SSLCipherSuite cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA;
77 SSLProtocol prot = kTLSProtocol1;
78 char password[200];
79 bool clientAuthEnable = false;
80 bool pauseOnError = false;
81 bool runForever = false;
82 bool mallocPause = false;
83
84 password[0] = 0;
85
86 extern int optind;
87 extern char *optarg;
88 int arg;
89 optind = 1;
90 while ((arg = getopt(argc, argv, "k:x:c:v:w:aBpm")) != -1) {
91 switch (arg) {
92 case 'k':
93 kcName = optarg;
94 break;
95 case 'x':
96 {
97 unsigned xsize = atoi(optarg);
98 if(xsize == 0) {
99 runForever = true;
100 /* and leave xferSize alone */
101 }
102 else {
103 xferSize = xsize;
104 }
105 break;
106 }
107 case 'c':
108 switch(optarg[0]) {
109 case 'a':
110 cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA;
111 break;
112 case 'r':
113 cipherSuite = SSL_RSA_WITH_RC4_128_SHA;
114 break;
115 case 'd':
116 cipherSuite = SSL_RSA_WITH_DES_CBC_SHA;
117 break;
118 case 'D':
119 cipherSuite = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
120 break;
121 case 'h':
122 cipherSuite = SSL_DH_anon_WITH_RC4_128_MD5;
123 diffieHellman = true;
124 break;
125 case 'H':
126 cipherSuite = SSL_DHE_DSS_WITH_DES_CBC_SHA;
127 diffieHellman = true;
128 break;
129 case 'A':
130 cipherSuite = TLS_RSA_WITH_AES_256_CBC_SHA;
131 break;
132 default:
133 usage(argv);
134 }
135 break;
136 case 'v':
137 switch(optarg[0]) {
138 case 't':
139 prot = kTLSProtocol1;
140 break;
141 case '2':
142 prot = kSSLProtocol2;
143 break;
144 case '3':
145 prot = kSSLProtocol3;
146 break;
147 default:
148 usage(argv);
149 }
150 break;
151 case 'w':
152 strcpy(password, optarg);
153 break;
154 case 'a':
155 clientAuthEnable = true;
156 break;
157 case 'p':
158 pauseOnError = true;
159 break;
160 case 'm':
161 mallocPause = true;
162 break;
163 default:
164 usage(argv);
165 }
166 }
167 if(optind != argc) {
168 usage(argv);
169 }
170
171 /* set up ring buffers */
172 ringBufSetup(&serverToClientRing, "serveToClient", numBufs, bufSize);
173 ringBufSetup(&clientToServerRing, "clientToServe", numBufs, bufSize);
174
175 /* get server SecIdentity */
176 idArray = getSslCerts(kcName,
177 CSSM_FALSE, /* encryptOnly */
178 CSSM_FALSE, /* completeCertChain */
179 NULL, /* anchorFile */
180 &kcRef);
181 if(idArray == NULL) {
182 printf("***Can't get signing cert from %s\n", kcName);
183 exit(1);
184 }
185 idRef = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, 0);
186 ortn = SecIdentityCopyCertificate(idRef, &anchorCert);
187 if(ortn) {
188 cssmPerror("SecIdentityCopyCertificate", ortn);
189 exit(1);
190 }
191 anchorArray = CFArrayCreate(NULL, (const void **)&anchorCert,
192 1, &kCFTypeArrayCallBacks);
193
194 /* unlock keychain? */
195 if(password[0]) {
196 ortn = SecKeychainUnlock(kcRef, strlen(password), password, true);
197 if(ortn) {
198 cssmPerror("SecKeychainUnlock", ortn);
199 /* oh well */
200 }
201 }
202 CFRelease(kcRef);
203
204 if(mallocPause) {
205 fpurge(stdin);
206 printf("Pausing for MallocDebug setup. CR to proceed: ");
207 getchar();
208 }
209
210 /* set up server side */
211 memset(&serverArgs, 0, sizeof(serverArgs));
212 serverArgs.idArray = idArray;
213 serverArgs.trustedRoots = anchorArray;
214 serverArgs.xferSize = xferSize;
215 serverArgs.xferBuf = serverBuf;
216 serverArgs.chunkSize = chunkSize;
217 serverArgs.runForever = runForever;
218 serverArgs.cipherSuite = cipherSuite;
219 serverArgs.prot = prot;
220 serverArgs.ringWrite = &serverToClientRing;
221 serverArgs.ringRead = &clientToServerRing;
222 serverArgs.goFlag = &clientArgs.iAmReady;
223 serverArgs.abortFlag = &abortFlag;
224 serverArgs.pauseOnError = pauseOnError;
225
226 /* set up client side */
227 memset(&clientArgs, 0, sizeof(clientArgs));
228 clientArgs.idArray = NULL; /* until we do client auth */
229 clientArgs.trustedRoots = anchorArray;
230 clientArgs.xferSize = xferSize;
231 clientArgs.xferBuf = clientBuf;
232 clientArgs.chunkSize = chunkSize;
233 clientArgs.runForever = runForever;
234 clientArgs.cipherSuite = cipherSuite;
235 clientArgs.prot = prot;
236 clientArgs.ringWrite = &clientToServerRing;
237 clientArgs.ringRead = &serverToClientRing;
238 clientArgs.goFlag = &serverArgs.iAmReady;
239 clientArgs.abortFlag = &abortFlag;
240 clientArgs.pauseOnError = pauseOnError;
241
242 /* fire up client thread */
243 result = pthread_create(&client_thread, NULL,
244 sslRbClientThread, &clientArgs);
245 if(result) {
246 printf("***pthread_create returned %d, aborting\n", result);
247 exit(1);
248 }
249
250 /*
251 * And the server pseudo thread. This returns when all data has been transferred.
252 */
253 ortn = sslRbServerThread(&serverArgs);
254
255 if(abortFlag) {
256 printf("***Test aborted.\n");
257 exit(1);
258 }
259
260 printf("\n");
261
262 if(mallocPause) {
263 fpurge(stdin);
264 printf("End of test. Pausing for MallocDebug analysis. CR to proceed: ");
265 getchar();
266 }
267
268 printf("SSL Protocol Version : %s\n",
269 sslGetProtocolVersionString(serverArgs.negotiatedProt));
270 printf("SSL Cipher : %s\n",
271 sslGetCipherSuiteString(serverArgs.negotiatedCipher));
272
273 printf("SSL Handshake : %f s\n",
274 serverArgs.startData - serverArgs.startHandshake);
275 printf("Data Transfer : %u bytes in %f s\n", (unsigned)xferSize,
276 serverArgs.endData - serverArgs.startHandshake);
277 printf(" : %.1f Kbytes/s\n",
278 xferSize / (serverArgs.endData - serverArgs.startHandshake) / 1024.0);
279 return 0;
280 }
281
282
283