1/*
2 * sslCipher.cpp - test SSL ciphersuite protocol negotiation, client
3 *				   and server side
4 */
5#include <Security/SecureTransport.h>
6#include <Security/Security.h>
7#include <clAppUtils/sslAppUtils.h>
8#include <clAppUtils/ioSock.h>
9#include <clAppUtils/sslThreading.h>
10#include <security_cdsa_utils/cuFileIo.h>
11#include <utilLib/common.h>
12#include <security_cdsa_utils/cuPrintCert.h>
13#include <security_utilities/threading.h>
14#include <security_utilities/devrandom.h>
15
16#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <string.h>
21#include <time.h>
22#include <ctype.h>
23#include <sys/param.h>
24
25/* default start port; caller can specify random start port */
26#define STARTING_PORT			5000
27
28#define MIN_RAND_PORT			1500
29#define MAX_RAND_PORT			7000
30
31/*
32 * Expected errors for negotiation failure
33 */
34#define SERVER_NEGOTIATE_FAIL	errSSLNegotiation
35#define CLIENT_NEGOTIATE_FAIL	errSSLPeerHandshakeFail
36
37#define RSA_SERVER_KC			"localcert"
38#define RSA_SERVER_ROOT			"localcert.cer"
39#define DSA_SERVER_KC			"dsacert"
40#define DSA_SERVER_ROOT			"dsacert.cer"
41
42#define DH_PARAM_FILE_512		"dhParams_512.der"
43#define DH_PARAM_FILE_1024		"dhParams_1024.der"
44
45/* main() fills these in using sslKeychainPath() */
46static char rsaKcPath[MAXPATHLEN];
47static char dsaKcPath[MAXPATHLEN];
48
49static void usage(char **argv)
50{
51	printf("Usage: %s [options]\n", argv[0]);
52	printf("options:\n");
53	printf("   q(uiet)\n");
54	printf("   v(erbose)\n");
55	printf("   p=startingPortNum\n");
56	printf("   t=startTestNum\n");
57	printf("   T=endTestNum\n");
58	printf("   g=startGroupNum\n");
59	printf("   l (large, 1024 bit Diffie-Hellman; default is 512)\n");
60	printf("   r(andom start port, default=%d)\n", STARTING_PORT);
61	printf("   b (non blocking I/O)\n");
62	printf("   s=serverCertName; default %s\n", RSA_SERVER_ROOT);
63	printf("   d=clientCertName; default %s\n", DSA_SERVER_ROOT);
64	printf("   R (ringBuffer I/O)\n");
65	exit(1);
66}
67
68/*
69 * Parameters defining one group of tests
70 */
71typedef struct {
72	const char		*groupDesc;
73	const char		*serveAcceptProts;
74	const char		*clientAcceptProts;
75	SSLProtocol		expectProt;
76} GroupParams;
77
78/*
79 * Certificate parameters
80 */
81typedef struct {
82	const char	*kcName;
83	const char	*kcPassword;	// last component of KC name */
84	const char 	*rootName;
85} CertParams;
86
87/*
88 * Parameters defining one individual test
89 */
90typedef struct {
91	const char				*testDesc;
92	SSLCipherSuite			expectCipher;
93	const CertParams		*certParams;
94	/*
95	 * In this test all failures are the same
96	 */
97	bool					shouldWork;
98} CipherParams;
99
100/* one of three cert params */
101static CertParams certRSA = 	{ rsaKcPath, RSA_SERVER_KC, RSA_SERVER_ROOT };
102static CertParams certDSA = 	{ dsaKcPath, DSA_SERVER_KC, DSA_SERVER_ROOT };
103static CertParams certNone = 	{NULL, NULL};
104
105/* Note we're skipping SSL2-specific testing for simplicity's sake */
106static const GroupParams sslGroupParams[] =
107{
108	{ "TLS1", "23t", "3t", kTLSProtocol1 },
109	{ "SSL3", "23",  "3t", kSSLProtocol3 }
110};
111#define NUM_GROUP_PARAMS	\
112	(sizeof(sslGroupParams) / sizeof(sslGroupParams[0]))
113
114/* some special-purpose ciphersuite arrays */
115
116#ifdef not_used
117/* just SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA */
118static const SSLCipherSuite suites_RsaExpDh40[] = {
119	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
120	SSL_NO_SUCH_CIPHERSUITE
121};
122#endif
123
124/* declare test name and expected cipher suite */
125#define SSL_NAC(cname) #cname, cname
126
127/*
128 * Note: the client is the only side which actually gets to
129 * prioritize its requested CipherSuites. The server has to
130 * go along with the first one on the client's list which the
131 * server implements.
132 */
133const CipherParams sslCipherParams[] =
134{
135	{
136		SSL_NAC(TLS_RSA_WITH_AES_128_CBC_SHA),
137		&certRSA, true
138	},
139	{
140		SSL_NAC(TLS_DH_DSS_WITH_AES_128_CBC_SHA),
141		&certDSA, false
142	},
143	{
144		SSL_NAC(TLS_DH_RSA_WITH_AES_128_CBC_SHA),
145		&certRSA, false
146	},
147	{
148		SSL_NAC(TLS_DHE_DSS_WITH_AES_128_CBC_SHA),
149		&certDSA, true
150	},
151	{
152		SSL_NAC(TLS_DHE_RSA_WITH_AES_128_CBC_SHA),
153		&certRSA, true
154	},
155	{
156		SSL_NAC(TLS_DH_anon_WITH_AES_128_CBC_SHA),
157		&certNone, true
158	},
159	{
160		SSL_NAC(TLS_RSA_WITH_AES_256_CBC_SHA),
161		&certRSA, true
162	},
163	{
164		SSL_NAC(TLS_DH_DSS_WITH_AES_256_CBC_SHA),
165		&certDSA, false
166	},
167	{
168		SSL_NAC(TLS_DH_RSA_WITH_AES_256_CBC_SHA),
169		&certRSA, false
170	},
171	{
172		SSL_NAC(TLS_DHE_DSS_WITH_AES_256_CBC_SHA),
173		&certDSA, true
174	},
175	{
176		SSL_NAC(TLS_DHE_RSA_WITH_AES_256_CBC_SHA),
177		&certRSA, true
178	},
179	{
180		SSL_NAC(TLS_DH_anon_WITH_AES_256_CBC_SHA),
181		&certNone, true
182	},
183	{
184		SSL_NAC(SSL_RSA_EXPORT_WITH_RC4_40_MD5),
185		&certRSA, true
186	},
187	{
188		SSL_NAC(SSL_RSA_WITH_RC4_128_MD5),
189		&certRSA, true
190	},
191	{
192		SSL_NAC(SSL_RSA_WITH_RC4_128_SHA),
193		&certRSA, true
194	},
195	{
196		SSL_NAC(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5),
197		&certRSA, true
198	},
199	/* skip SSL_RSA_WITH_IDEA_CBC_SHA, check later as unimpl */
200	{
201		SSL_NAC(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA),
202		&certRSA, true
203	},
204	{
205		SSL_NAC(SSL_RSA_WITH_DES_CBC_SHA),
206		&certRSA, true
207	},
208	{
209		SSL_NAC(SSL_RSA_WITH_3DES_EDE_CBC_SHA),
210		&certRSA, true
211	},
212	{
213		SSL_NAC(SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA),
214		&certDSA, false
215	},
216	{
217		SSL_NAC(SSL_DH_DSS_WITH_DES_CBC_SHA),
218		&certDSA, false
219	},
220	{
221		SSL_NAC(SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA),
222		&certDSA, false
223	},
224	{
225		SSL_NAC(SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA),
226		&certRSA, false
227	},
228	{
229		SSL_NAC(SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA),
230		&certDSA, true
231	},
232	{
233		SSL_NAC(SSL_DHE_DSS_WITH_DES_CBC_SHA),
234		&certDSA, true
235	},
236	{
237		SSL_NAC(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA),
238		&certDSA, true
239	},
240	{
241		SSL_NAC(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA),
242		&certRSA, true
243	},
244	{
245		SSL_NAC(SSL_DHE_RSA_WITH_DES_CBC_SHA),
246		&certRSA, true
247	},
248	{
249		SSL_NAC(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA),
250		&certRSA, true
251	},
252	{
253		SSL_NAC(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5),
254		&certNone, true
255	},
256	{
257		SSL_NAC(SSL_DH_anon_WITH_RC4_128_MD5),
258		&certNone, true
259	},
260	{
261		SSL_NAC(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA),
262		&certNone, true
263	},
264	{
265		SSL_NAC(SSL_DH_anon_WITH_DES_CBC_SHA),
266		&certNone, true
267	},
268	{
269		SSL_NAC(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA),
270		&certNone, true
271	},
272	{
273		SSL_NAC(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA),
274		&certNone, true
275	},
276	{
277		SSL_NAC(SSL_FORTEZZA_DMS_WITH_NULL_SHA),
278		&certNone, false
279	},
280	{
281		SSL_NAC(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA),
282		&certNone, false
283	},
284};
285
286#define NUM_CIPHER_PARAMS	\
287	(sizeof(sslCipherParams) / sizeof(sslCipherParams[0]))
288
289#define IGNORE_SIGPIPE	1
290#if 	IGNORE_SIGPIPE
291#include <signal.h>
292
293void sigpipe(int sig)
294{
295}
296#endif	/* IGNORE_SIGPIPE */
297
298/*
299 * Default params for each test. Main() will make a copy of this and
300 * adjust its copy on a per-test basis.
301 */
302static SslAppTestParams serverDefaults =
303{
304	"no name here",
305	false,				// skipHostNameCHeck
306	0,					// port - test must set this
307	NULL, NULL,			// RingBuffers
308	false,				// noProtSpec
309	kSSLProtocolUnknown,// not used
310	NULL,				// acceptedProts
311	NULL,				// myCerts
312	NULL,				// password
313	true,				// idIsTrustedRoot
314	false,				// disableCertVerify
315	NULL,				// anchorFile
316	false,				// replaceAnchors
317	kNeverAuthenticate,
318	false,				// resumeEnable
319	NULL,				// ciphers - default - server accepts all
320	false,				// nonBlocking
321	NULL,				// dhParams
322	0,					// dhParamsLen
323	noErr,				// expectRtn
324	kTLSProtocol1,		// expectVersion
325	kSSLClientCertNone,
326	SSL_NULL_WITH_NULL_NULL,
327	false,				// quiet
328	false,				// silent
329	false,				// verbose
330	{0},				// lock
331	{0},				// cond
332	false,				// serverReady
333	0,					// clientDone
334	false,				// serverAbort
335	/* returned */
336	kSSLProtocolUnknown,
337	SSL_NULL_WITH_NULL_NULL,
338	kSSLClientCertNone,
339	noHardwareErr
340
341};
342
343SslAppTestParams clientDefaults =
344{
345	"localhost",
346	false,				// skipHostNameCHeck
347	0,					// port - test must set this
348	NULL, NULL,			// RingBuffers
349	false,				// noProtSpec
350	kSSLProtocolUnknown,// not used
351	NULL,				// acceptedProts
352	NULL,				// myCertKcName
353	NULL,				// password
354	true,				// idIsTrustedRoot
355	false,				// disableCertVerify
356	NULL,				// anchorFile
357	true,				// replaceAnchors
358	kNeverAuthenticate,
359	false,				// resumeEnable
360	NULL,				// ciphers - set in test loop
361	false,				// nonBlocking
362	NULL,				// dhParams
363	0,					// dhParamsLen
364	noErr,				// expectRtn
365	kTLSProtocol1,		// expectVersion
366	kSSLClientCertNone,
367	SSL_NULL_WITH_NULL_NULL,
368	false,				// quiet
369	false,				// silent
370	false,				// verbose
371	{0},				// lock
372	{0},				// cond
373	false,				// serverReady
374	0,					// clientDone
375	false,				// serverAbort
376	/* returned */
377	kSSLProtocolUnknown,
378	SSL_NULL_WITH_NULL_NULL,
379	kSSLClientCertNone,
380	noHardwareErr
381};
382
383
384int main(int argc, char **argv)
385{
386	int 				ourRtn = 0;
387	char	 			*argp;
388	SslAppTestParams 	clientParams;
389	SslAppTestParams 	serverParams;
390	unsigned short		portNum = STARTING_PORT;
391	const GroupParams	*groupParams;
392	const CipherParams	*cipherParams;
393	unsigned			testNum;
394	unsigned			groupNum;
395	int					thisRtn;
396	SSLCipherSuite		clientCiphers[3];
397	SSLCipherSuite		serverCiphers[3];
398	RingBuffer			serverToClientRing;
399	RingBuffer			clientToServerRing;
400	bool				ringBufferIo = false;
401
402	/* user-spec'd variables */
403	unsigned			startTest = 0;
404	unsigned			endTest = NUM_CIPHER_PARAMS;
405	unsigned			startGroup = 0;
406	const char			*dhParamFile = DH_PARAM_FILE_512;
407
408	for(int arg=1; arg<argc; arg++) {
409		argp = argv[arg];
410		switch(argp[0]) {
411			case 'q':
412				serverDefaults.quiet = clientDefaults.quiet = true;
413				break;
414			case 'v':
415				serverDefaults.verbose = clientDefaults.verbose = true;
416				break;
417			case 'p':
418				portNum = atoi(&argp[2]);
419				break;
420			case 't':
421				startTest = atoi(&argp[2]);
422				break;
423			case 'T':
424				endTest = atoi(&argp[2]) + 1;
425				break;
426			case 'g':
427				startGroup = atoi(&argp[2]);
428				break;
429			case 'b':
430				serverDefaults.nonBlocking = clientDefaults.nonBlocking =
431						true;
432				break;
433			case 'l':
434				dhParamFile = DH_PARAM_FILE_1024;
435				break;
436			case 'r':
437				portNum = genRand(MIN_RAND_PORT, MAX_RAND_PORT);
438				break;
439			case 's':
440				certRSA.rootName = &argp[2];
441				break;
442			case 'd':
443				certDSA.rootName = &argp[2];
444				break;
445			case 'R':
446				ringBufferIo = true;
447				break;
448			default:
449				usage(argv);
450		}
451	}
452
453	if(sslCheckFile(certRSA.rootName)) {
454		exit(1);
455	}
456	if(sslCheckFile(certDSA.rootName)) {
457		exit(1);
458	}
459	if(ringBufferIo) {
460		/* set up ring buffers */
461		ringBufSetup(&serverToClientRing, "serveToClient", DEFAULT_NUM_RB_BUFS, DEFAULT_BUF_RB_SIZE);
462		ringBufSetup(&clientToServerRing, "clientToServe", DEFAULT_NUM_RB_BUFS, DEFAULT_BUF_RB_SIZE);
463		serverDefaults.serverToClientRing = &serverToClientRing;
464		serverDefaults.clientToServerRing = &clientToServerRing;
465		clientDefaults.serverToClientRing = &serverToClientRing;
466		clientDefaults.clientToServerRing = &clientToServerRing;
467	}
468
469#if IGNORE_SIGPIPE
470	signal(SIGPIPE, sigpipe);
471	#endif
472
473	/* convert keychain names to paths for root */
474	sslKeychainPath(RSA_SERVER_KC, rsaKcPath);
475	sslKeychainPath(DSA_SERVER_KC, dsaKcPath);
476
477	/* Diffie-Hellman params, we're going to need them */
478	int r = readFile(dhParamFile, (unsigned char **)&serverDefaults.dhParams,
479		&serverDefaults.dhParamsLen);
480	if(r) {
481		printf("***Error reading diffie-hellman params from %s; aborting\n",
482			dhParamFile);
483		exit(1);
484	}
485
486	testStartBanner("sslCipher", argc, argv);
487
488	serverParams.port = portNum - 1;	// gets incremented by SSL_THR_SETUP
489
490	/*
491	 * To enable negotiation failures to occur, we have to pass
492	 * in ciphersuite arrays which contain at least one valid
493	 * ciphersuite to both client and server, but they can not
494	 * be the same (or else that valid suite will be used).
495	 */
496	clientCiphers[1] = SSL_RSA_WITH_RC4_128_MD5;
497	serverCiphers[1] = SSL_RSA_WITH_RC4_128_SHA;
498	clientCiphers[2] = SSL_NO_SUCH_CIPHERSUITE;
499	serverCiphers[2] = SSL_NO_SUCH_CIPHERSUITE;
500
501	for(groupNum=startGroup; groupNum<NUM_GROUP_PARAMS; groupNum++) {
502		groupParams = &sslGroupParams[groupNum];
503		if(!serverDefaults.quiet) {
504			printf("...%s\n", groupParams->groupDesc);
505		}
506		for(testNum=startTest; testNum<endTest; testNum++) {
507			cipherParams = &sslCipherParams[testNum];
508			SSL_THR_SETUP(serverParams, clientParams, clientDefaults,
509					serverDefault);
510			if(ringBufferIo) {
511				ringBufferReset(&serverToClientRing);
512				ringBufferReset(&clientToServerRing);
513			}
514			/* per-group (must be after SSL_THR_SETUP) */
515			serverParams.acceptedProts = groupParams->serveAcceptProts;
516			clientParams.acceptedProts = groupParams->clientAcceptProts;
517			serverParams.expectVersion = groupParams->expectProt;
518			clientParams.expectVersion = groupParams->expectProt;
519
520			/* per-test */
521			clientCiphers[0] = cipherParams->expectCipher;
522			serverCiphers[0] = cipherParams->expectCipher;
523			clientParams.ciphers = clientCiphers;
524			serverParams.ciphers = serverCiphers;
525			serverParams.expectCipher = cipherParams->expectCipher;
526			clientParams.expectCipher = cipherParams->expectCipher;
527
528			const CertParams *certParams = cipherParams->certParams;
529			serverParams.myCertKcName = certParams->kcName;
530			serverParams.password = certParams->kcPassword;
531			clientParams.anchorFile = certParams->rootName;
532
533			if(cipherParams->shouldWork) {
534				serverParams.expectRtn = noErr;
535				clientParams.expectRtn = noErr;
536			}
537			else {
538				serverParams.expectRtn = SERVER_NEGOTIATE_FAIL;
539				clientParams.expectRtn = CLIENT_NEGOTIATE_FAIL;
540
541				/* server completed protocol version negotiation,
542				 * but client didn't */
543				clientParams.expectVersion = kSSLProtocolUnknown;
544			}
545			SSL_THR_RUN_NUM(serverParams, clientParams,
546				cipherParams->testDesc, ourRtn, testNum);
547		}
548	}
549
550done:
551	if(!clientParams.quiet) {
552		if(ourRtn == 0) {
553			printf("===== %s test PASSED =====\n", argv[0]);
554		}
555		else {
556			printf("****%s FAIL: %d errors detected\n", argv[0],ourRtn);
557		}
558	}
559
560	return ourRtn;
561}
562