1/*
2 * Copyright (c) 2006-2008,2010-2013 Apple Inc. All Rights Reserved.
3 */
4
5#include "sslAppUtils.h"
6//#include "sslThreading.h"
7//#include "identPicker.h"
8//#include <utilLib/common.h>
9#include <stdlib.h>
10#include <stdio.h>
11#include <sys/param.h>
12#include <Security/SecBase.h>
13
14#include <CoreFoundation/CoreFoundation.h>
15#include <Security/Security.h>
16#include <Security/SecIdentityPriv.h>
17#include <AssertMacros.h>
18#include <sys/time.h>
19
20#include "utilities/SecCFRelease.h"
21
22/* Set true when PR-3074739 is merged to TOT */
23#define NEW_SSL_ERRS_3074739		1
24
25
26const char *sslGetCipherSuiteString(SSLCipherSuite cs)
27{
28	static char noSuite[40];
29
30	switch(cs) {
31		case SSL_NULL_WITH_NULL_NULL:
32			return "SSL_NULL_WITH_NULL_NULL";
33		case SSL_RSA_WITH_NULL_MD5:
34			return "SSL_RSA_WITH_NULL_MD5";
35		case SSL_RSA_WITH_NULL_SHA:
36			return "SSL_RSA_WITH_NULL_SHA";
37		case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
38			return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
39		case SSL_RSA_WITH_RC4_128_MD5:
40			return "SSL_RSA_WITH_RC4_128_MD5";
41		case SSL_RSA_WITH_RC4_128_SHA:
42			return "SSL_RSA_WITH_RC4_128_SHA";
43		case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
44			return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
45		case SSL_RSA_WITH_IDEA_CBC_SHA:
46			return "SSL_RSA_WITH_IDEA_CBC_SHA";
47		case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
48			return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
49		case SSL_RSA_WITH_DES_CBC_SHA:
50			return "SSL_RSA_WITH_DES_CBC_SHA";
51		case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
52			return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
53		case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
54			return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
55		case SSL_DH_DSS_WITH_DES_CBC_SHA:
56			return "SSL_DH_DSS_WITH_DES_CBC_SHA";
57		case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:
58			return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
59		case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
60			return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
61		case SSL_DH_RSA_WITH_DES_CBC_SHA:
62			return "SSL_DH_RSA_WITH_DES_CBC_SHA";
63		case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:
64			return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
65		case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
66			return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
67		case SSL_DHE_DSS_WITH_DES_CBC_SHA:
68			return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
69		case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
70			return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
71		case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
72			return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
73		case SSL_DHE_RSA_WITH_DES_CBC_SHA:
74			return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
75		case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
76			return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
77		case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
78			return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
79		case SSL_DH_anon_WITH_RC4_128_MD5:
80			return "SSL_DH_anon_WITH_RC4_128_MD5";
81		case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
82			return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
83		case SSL_DH_anon_WITH_DES_CBC_SHA:
84			return "SSL_DH_anon_WITH_DES_CBC_SHA";
85		case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
86			return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
87		case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
88			return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
89		case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
90			return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
91		case SSL_RSA_WITH_RC2_CBC_MD5:
92			return "SSL_RSA_WITH_RC2_CBC_MD5";
93		case SSL_RSA_WITH_IDEA_CBC_MD5:
94			return "SSL_RSA_WITH_IDEA_CBC_MD5";
95		case SSL_RSA_WITH_DES_CBC_MD5:
96			return "SSL_RSA_WITH_DES_CBC_MD5";
97		case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
98			return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
99		case SSL_NO_SUCH_CIPHERSUITE:
100			return "SSL_NO_SUCH_CIPHERSUITE";
101		case TLS_RSA_WITH_AES_128_CBC_SHA:
102			return "TLS_RSA_WITH_AES_128_CBC_SHA";
103		case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
104			return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
105		case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
106			return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
107		case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
108			return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
109		case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
110			return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
111		case TLS_DH_anon_WITH_AES_128_CBC_SHA:
112			return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
113		case TLS_RSA_WITH_AES_256_CBC_SHA:
114			return "TLS_RSA_WITH_AES_256_CBC_SHA";
115		case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
116			return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
117		case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
118			return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
119		case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
120			return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
121		case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
122			return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
123		case TLS_DH_anon_WITH_AES_256_CBC_SHA:
124			return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
125
126		default:
127			sprintf(noSuite, "Unknown (%d)", (unsigned)cs);
128			return noSuite;
129	}
130}
131
132/*
133 * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion -
134 * return a string representation.
135 */
136const char *sslGetProtocolVersionString(SSLProtocol prot)
137{
138	static char noProt[20];
139
140	switch(prot) {
141		case kSSLProtocolUnknown:
142			return "kSSLProtocolUnknown";
143		case kSSLProtocol2:
144			return "kSSLProtocol2";
145		case kSSLProtocol3:
146			return "kSSLProtocol3";
147		case kSSLProtocol3Only:
148			return "kSSLProtocol3Only";
149		case kTLSProtocol1:
150			return "kTLSProtocol1";
151		case kTLSProtocol1Only:
152			return "kTLSProtocol1Only";
153        case kTLSProtocol11:
154			return "kTLSProtocol11";
155        case kTLSProtocol12:
156			return "kTLSProtocol12";
157		default:
158			sprintf(noProt, "Unknown (%d)", (unsigned)prot);
159			return noProt;
160	}
161}
162
163/*
164 * Return string representation of SecureTransport-related OSStatus.
165 */
166const char *sslGetSSLErrString(OSStatus err)
167{
168	static char errSecSuccessStr[20];
169
170	switch(err) {
171		case errSecSuccess:
172			return "errSecSuccess";
173		case errSecAllocate:
174			return "errSecAllocate";
175		case errSecParam:
176			return "errSecParam";
177		case errSecUnimplemented:
178			return "errSecUnimplemented";
179		case errSecIO:
180			return "errSecIO";
181		case errSecBadReq:
182			return "errSecBadReq";
183		case errSSLProtocol:
184			return "errSSLProtocol";
185		case errSSLNegotiation:
186			return "errSSLNegotiation";
187		case errSSLFatalAlert:
188			return "errSSLFatalAlert";
189		case errSSLWouldBlock:
190			return "errSSLWouldBlock";
191		case errSSLSessionNotFound:
192			return "errSSLSessionNotFound";
193		case errSSLClosedGraceful:
194			return "errSSLClosedGraceful";
195		case errSSLClosedAbort:
196			return "errSSLClosedAbort";
197   		case errSSLXCertChainInvalid:
198			return "errSSLXCertChainInvalid";
199		case errSSLBadCert:
200			return "errSSLBadCert";
201		case errSSLCrypto:
202			return "errSSLCrypto";
203		case errSSLInternal:
204			return "errSSLInternal";
205		case errSSLModuleAttach:
206			return "errSSLModuleAttach";
207		case errSSLUnknownRootCert:
208			return "errSSLUnknownRootCert";
209		case errSSLNoRootCert:
210			return "errSSLNoRootCert";
211		case errSSLCertExpired:
212			return "errSSLCertExpired";
213		case errSSLCertNotYetValid:
214			return "errSSLCertNotYetValid";
215		case errSSLClosedNoNotify:
216			return "errSSLClosedNoNotify";
217		case errSSLBufferOverflow:
218			return "errSSLBufferOverflow";
219		case errSSLBadCipherSuite:
220			return "errSSLBadCipherSuite";
221		/* TLS/Panther addenda */
222		case errSSLPeerUnexpectedMsg:
223			return "errSSLPeerUnexpectedMsg";
224		case errSSLPeerBadRecordMac:
225			return "errSSLPeerBadRecordMac";
226		case errSSLPeerDecryptionFail:
227			return "errSSLPeerDecryptionFail";
228		case errSSLPeerRecordOverflow:
229			return "errSSLPeerRecordOverflow";
230		case errSSLPeerDecompressFail:
231			return "errSSLPeerDecompressFail";
232		case errSSLPeerHandshakeFail:
233			return "errSSLPeerHandshakeFail";
234		case errSSLPeerBadCert:
235			return "errSSLPeerBadCert";
236		case errSSLPeerUnsupportedCert:
237			return "errSSLPeerUnsupportedCert";
238		case errSSLPeerCertRevoked:
239			return "errSSLPeerCertRevoked";
240		case errSSLPeerCertExpired:
241			return "errSSLPeerCertExpired";
242		case errSSLPeerCertUnknown:
243			return "errSSLPeerCertUnknown";
244		case errSSLIllegalParam:
245			return "errSSLIllegalParam";
246		case errSSLPeerUnknownCA:
247			return "errSSLPeerUnknownCA";
248		case errSSLPeerAccessDenied:
249			return "errSSLPeerAccessDenied";
250		case errSSLPeerDecodeError:
251			return "errSSLPeerDecodeError";
252		case errSSLPeerDecryptError:
253			return "errSSLPeerDecryptError";
254		case errSSLPeerExportRestriction:
255			return "errSSLPeerExportRestriction";
256		case errSSLPeerProtocolVersion:
257			return "errSSLPeerProtocolVersion";
258		case errSSLPeerInsufficientSecurity:
259			return "errSSLPeerInsufficientSecurity";
260		case errSSLPeerInternalError:
261			return "errSSLPeerInternalError";
262		case errSSLPeerUserCancelled:
263			return "errSSLPeerUserCancelled";
264		case errSSLPeerNoRenegotiation:
265			return "errSSLPeerNoRenegotiation";
266		case errSSLHostNameMismatch:
267			return "errSSLHostNameMismatch";
268		case errSSLConnectionRefused:
269			return "errSSLConnectionRefused";
270		case errSSLDecryptionFail:
271			return "errSSLDecryptionFail";
272		case errSSLBadRecordMac:
273			return "errSSLBadRecordMac";
274		case errSSLRecordOverflow:
275			return "errSSLRecordOverflow";
276		case errSSLBadConfiguration:
277			return "errSSLBadConfiguration";
278
279		/* some from the Sec layer */
280		case errSecNotAvailable:			return "errSecNotAvailable";
281		case errSecDuplicateItem:			return "errSecDuplicateItem";
282		case errSecItemNotFound:			return "errSecItemNotFound";
283#if 0
284		case errSessionInvalidId:			return "errSessionInvalidId";
285		case errSessionInvalidAttributes:	return "errSessionInvalidAttributes";
286		case errSessionAuthorizationDenied:	return "errSessionAuthorizationDenied";
287		case errSessionInternal:			return "errSessionInternal";
288		case errSessionInvalidFlags:		return "errSessionInvalidFlags";
289#endif
290
291		default:
292#if 0
293			if (err < (CSSM_BASE_ERROR +
294			         (CSSM_ERRORCODE_MODULE_EXTENT * 8)))
295			{
296				/* assume CSSM error */
297				return cssmErrToStr(err);
298			}
299			else
300#endif
301			{
302				sprintf(errSecSuccessStr, "Unknown (%d)", (unsigned)err);
303				return errSecSuccessStr;
304			}
305	}
306}
307
308void printSslErrStr(
309	const char 	*op,
310	OSStatus 	err)
311{
312	printf("*** %s: %s\n", op, sslGetSSLErrString(err));
313}
314
315const char *sslGetClientCertStateString(SSLClientCertificateState state)
316{
317	static char noState[20];
318
319	switch(state) {
320		case kSSLClientCertNone:
321			return "ClientCertNone";
322		case kSSLClientCertRequested:
323			return "CertRequested";
324		case kSSLClientCertSent:
325			return "ClientCertSent";
326		case kSSLClientCertRejected:
327			return "ClientCertRejected";
328		default:
329			sprintf(noState, "Unknown (%d)", (unsigned)state);
330			return noState;
331	}
332
333}
334
335/*
336 * Convert a keychain name (which may be NULL) into the CFArrayRef required
337 * by SSLSetCertificate. This is a bare-bones example of this operation,
338 * since it requires and assumes that there is exactly one SecIdentity
339 * in the keychain - i.e., there is exactly one matching cert/private key
340 * pair. A real world server would probably search a keychain for a SecIdentity
341 * matching some specific criteria.
342 */
343CFArrayRef getSslCerts(
344	const char			*kcName,				// may be NULL, i.e., use default
345	bool                encryptOnly,
346	bool                completeCertChain,
347	const char			*anchorFile,			// optional trusted anchor
348	SecKeychainRef		*pKcRef)				// RETURNED
349{
350#if 0
351	SecKeychainRef 		kcRef = nil;
352	OSStatus			ortn;
353
354	*pKcRef = nil;
355
356	/* pick a keychain */
357	if(kcName) {
358		ortn = SecKeychainOpen(kcName, &kcRef);
359		if(ortn) {
360			printf("SecKeychainOpen returned %d.\n", (int)ortn);
361			printf("Cannot open keychain at %s. Aborting.\n", kcName);
362			return NULL;
363		}
364	}
365	else {
366		/* use default keychain */
367		ortn = SecKeychainCopyDefault(&kcRef);
368		if(ortn) {
369			printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn);
370			return nil;
371		}
372	}
373	*pKcRef = kcRef;
374	return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile);
375#else
376	SecCertificateRef cert = NULL;
377	SecIdentityRef identity = NULL;
378	CFMutableArrayRef certificates = NULL, result = NULL;
379	CFMutableDictionaryRef certQuery = NULL, keyQuery = NULL, keyResult = NULL;
380	SecTrustRef trust = NULL;
381	SecKeyRef key = NULL;
382	CFTypeRef pkdigest = NULL;
383
384	// Find the first private key in the keychain and return both it's
385	// attributes and a ref to it.
386	require(keyQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut);
387	CFDictionaryAddValue(keyQuery, kSecClass, kSecClassKey);
388	CFDictionaryAddValue(keyQuery, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
389	CFDictionaryAddValue(keyQuery, kSecReturnRef, kCFBooleanTrue);
390	CFDictionaryAddValue(keyQuery, kSecReturnAttributes, kCFBooleanTrue);
391	require_noerr(SecItemCopyMatching(keyQuery, (CFTypeRef *)&keyResult),
392		errOut);
393	require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef),
394		errOut);
395	require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel),
396		errOut);
397
398	// Find the first certificate that has the same public key hash as the
399	// returned private key and return it as a ref.
400	require(certQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut);
401	CFDictionaryAddValue(certQuery, kSecClass, kSecClassCertificate);
402	CFDictionaryAddValue(certQuery, kSecAttrPublicKeyHash, pkdigest);
403	CFDictionaryAddValue(certQuery, kSecReturnRef, kCFBooleanTrue);
404	require_noerr(SecItemCopyMatching(certQuery, (CFTypeRef *)&cert), errOut);
405
406	// Create an identity from the key and certificate.
407	require(identity = SecIdentityCreate(NULL, cert, key), errOut);
408
409	// Build a (partial) certificate chain from cert
410	require(certificates = CFArrayCreateMutable(NULL, 0,
411		&kCFTypeArrayCallBacks), errOut);
412	CFArrayAppendValue(certificates, cert);
413	require_noerr(SecTrustCreateWithCertificates(certificates, NULL, &trust),
414		errOut);
415	SecTrustResultType tresult;
416	require_noerr(SecTrustEvaluate(trust, &tresult), errOut);
417
418	CFIndex certCount, ix;
419	// We need at least 1 certificate
420	require(certCount = SecTrustGetCertificateCount(trust), errOut);
421
422	// Build a result where element 0 is the identity and the other elements
423	// are the certs in the chain starting at the first intermediate up to the
424	// anchor, if we found one, or as far as we were able to build the chain
425	// if not.
426	require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks),
427		errOut);
428
429	// We are commited to returning a result now, so do not use require below
430	// this line without setting result to NULL again.
431	CFArrayAppendValue(result, identity);
432	for (ix = 1; ix < certCount; ++ix) {
433		CFArrayAppendValue(result, SecTrustGetCertificateAtIndex(trust, ix));
434	}
435
436errOut:
437	CFReleaseSafe(trust);
438	CFReleaseSafe(certificates);
439	CFReleaseSafe(identity);
440	CFReleaseSafe(cert);
441	CFReleaseSafe(certQuery);
442	CFReleaseSafe(keyResult);
443	CFReleaseSafe(keyQuery);
444
445    return result;
446#endif
447}
448
449#if 0
450/*
451 * Determine if specified SecCertificateRef is a self-signed cert.
452 * We do this by comparing the subject and issuerr names; no cryptographic
453 * verification is performed.
454 *
455 * Returns true if the cert appears to be a root.
456 */
457static bool isCertRefRoot(
458	SecCertificateRef certRef)
459{
460	bool brtn = false;
461#if 0
462	/* just search for the two attrs we want */
463	UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr};
464	SecKeychainAttributeInfo attrInfo;
465	attrInfo.count = 2;
466	attrInfo.tag = tags;
467	attrInfo.format = NULL;
468	SecKeychainAttributeList *attrList = NULL;
469	SecKeychainAttribute *attr1 = NULL;
470	SecKeychainAttribute *attr2 = NULL;
471
472	OSStatus ortn = SecKeychainItemCopyAttributesAndData(
473		(SecKeychainItemRef)certRef,
474		&attrInfo,
475		NULL,			// itemClass
476		&attrList,
477		NULL,			// length - don't need the data
478		NULL);			// outData
479	if(ortn) {
480		cssmPerror("SecKeychainItemCopyAttributesAndData", ortn);
481		/* may want to be a bit more robust here, but this should
482		 * never happen */
483		return false;
484	}
485	/* subsequent errors to errOut: */
486
487	if((attrList == NULL) || (attrList->count != 2)) {
488		printf("***Unexpected result fetching label attr\n");
489		goto errOut;
490	}
491
492	/* rootness is just byte-for-byte compare of the two names */
493	attr1 = &attrList->attr[0];
494	attr2 = &attrList->attr[1];
495	if(attr1->length == attr2->length) {
496		if(memcmp(attr1->data, attr2->data, attr1->length) == 0) {
497			brtn = true;
498		}
499	}
500errOut:
501	SecKeychainItemFreeAttributesAndData(attrList, NULL);
502#endif
503	return brtn;
504}
505#endif
506
507#if 0
508/*
509 * Given a SecIdentityRef, do our best to construct a complete, ordered, and
510 * verified cert chain, returning the result in a CFArrayRef. The result is
511 * suitable for use when calling SSLSetCertificate().
512 */
513OSStatus sslCompleteCertChain(
514	SecIdentityRef 		identity,
515	SecCertificateRef	trustedAnchor,	// optional additional trusted anchor
516	bool 				includeRoot, 	// include the root in outArray
517	CFArrayRef			*outArray)		// created and RETURNED
518{
519	CFMutableArrayRef 			certArray;
520	SecTrustRef					secTrust = NULL;
521	SecPolicyRef				policy = NULL;
522	SecPolicySearchRef			policySearch = NULL;
523	SecTrustResultType			secTrustResult;
524	CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv;			// not used
525	CFArrayRef					certChain = NULL;   // constructed chain
526	CFIndex 					numResCerts;
527
528	certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
529	CFArrayAppendValue(certArray, identity);
530
531	/*
532	 * Case 1: identity is a root; we're done. Note that this case
533	 * overrides the includeRoot argument.
534	 */
535	SecCertificateRef certRef;
536	OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef);
537	if(ortn) {
538		/* should never happen */
539		cssmPerror("SecIdentityCopyCertificate", ortn);
540		return ortn;
541	}
542	bool isRoot = isCertRefRoot(certRef);
543	if(isRoot) {
544		*outArray = certArray;
545		CFRelease(certRef);
546		return errSecSuccess;
547	}
548
549	/*
550	 * Now use SecTrust to get a complete cert chain, using all of the
551	 * user's keychains to look for intermediate certs.
552	 * NOTE this does NOT handle root certs which are not in the system
553	 * root cert DB. (The above case, where the identity is a root cert, does.)
554	 */
555	CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
556	CFArraySetValueAtIndex(subjCerts, 0, certRef);
557
558	/* the array owns the subject cert ref now */
559	CFRelease(certRef);
560
561	/* Get a SecPolicyRef for generic X509 cert chain verification */
562	ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
563		&CSSMOID_APPLE_X509_BASIC,
564		NULL,				// value
565		&policySearch);
566	if(ortn) {
567		cssmPerror("SecPolicySearchCreate", ortn);
568		goto errOut;
569	}
570	ortn = SecPolicySearchCopyNext(policySearch, &policy);
571	if(ortn) {
572		cssmPerror("SecPolicySearchCopyNext", ortn);
573		goto errOut;
574	}
575
576	/* build a SecTrustRef for specified policy and certs */
577	ortn = SecTrustCreateWithCertificates(subjCerts,
578		policy, &secTrust);
579	if(ortn) {
580		cssmPerror("SecTrustCreateWithCertificates", ortn);
581		goto errOut;
582	}
583
584	if(trustedAnchor) {
585		/*
586		 * Tell SecTrust to trust this one in addition to the current
587		 * trusted system-wide anchors.
588		 */
589		CFMutableArrayRef newAnchors;
590		CFArrayRef currAnchors;
591
592		ortn = SecTrustCopyAnchorCertificates(&currAnchors);
593		if(ortn) {
594			/* should never happen */
595			cssmPerror("SecTrustCopyAnchorCertificates", ortn);
596			goto errOut;
597		}
598		newAnchors = CFArrayCreateMutableCopy(NULL,
599			CFArrayGetCount(currAnchors) + 1,
600			currAnchors);
601		CFRelease(currAnchors);
602		CFArrayAppendValue(newAnchors, trustedAnchor);
603		ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
604		CFRelease(newAnchors);
605		if(ortn) {
606			cssmPerror("SecTrustSetAnchorCertificates", ortn);
607			goto errOut;
608		}
609	}
610	/* evaluate: GO */
611	ortn = SecTrustEvaluate(secTrust, &secTrustResult);
612	if(ortn) {
613		cssmPerror("SecTrustEvaluate", ortn);
614		goto errOut;
615	}
616	switch(secTrustResult) {
617		case kSecTrustResultUnspecified:
618			/* cert chain valid, no special UserTrust assignments */
619		case kSecTrustResultProceed:
620			/* cert chain valid AND user explicitly trusts this */
621			break;
622		default:
623			/*
624			 * Cert chain construction failed.
625			 * Just go with the single subject cert we were given.
626			 */
627			printf("***Warning: could not construct completed cert chain\n");
628			ortn = errSecSuccess;
629			goto errOut;
630	}
631
632	/* get resulting constructed cert chain */
633	ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
634	if(ortn) {
635		cssmPerror("SecTrustEvaluate", ortn);
636		goto errOut;
637	}
638
639	/*
640	 * Copy certs from constructed chain to our result array, skipping
641	 * the leaf (which is already there, as a SecIdentityRef) and possibly
642	 * a root.
643	 */
644	numResCerts = CFArrayGetCount(certChain);
645	if(numResCerts < 2) {
646		/*
647		 * Can't happen: if subject was a root, we'd already have returned.
648		 * If chain doesn't verify to a root, we'd have bailed after
649		 * SecTrustEvaluate().
650		 */
651		printf("***sslCompleteCertChain screwup: numResCerts %d\n",
652			(int)numResCerts);
653		ortn = errSecSuccess;
654		goto errOut;
655	}
656	if(!includeRoot) {
657		/* skip the last (root) cert) */
658		numResCerts--;
659	}
660	for(CFIndex dex=1; dex<numResCerts; dex++) {
661		certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
662		CFArrayAppendValue(certArray, certRef);
663	}
664errOut:
665	/* clean up */
666	if(secTrust) {
667		CFRelease(secTrust);
668	}
669	if(subjCerts) {
670		CFRelease(subjCerts);
671	}
672	if(policy) {
673		CFRelease(policy);
674	}
675	if(policySearch) {
676		CFRelease(policySearch);
677	}
678	*outArray = certArray;
679	return ortn;
680}
681
682
683/*
684 * Given an open keychain, find a SecIdentityRef and munge it into
685 * a CFArrayRef required by SSLSetCertificate().
686 */
687CFArrayRef sslKcRefToCertArray(
688	SecKeychainRef		kcRef,
689	bool                encryptOnly,
690	bool                completeCertChain,
691	const char			*trustedAnchorFile)
692{
693	/* quick check to make sure the keychain exists */
694	SecKeychainStatus kcStat;
695	OSStatus ortn = SecKeychainGetStatus(kcRef, &kcStat);
696	if(ortn) {
697		printSslErrStr("SecKeychainGetStatus", ortn);
698		printf("Can not open keychain. Aborting.\n");
699		return nil;
700	}
701
702	/*
703	 * Search for "any" identity matching specified key use;
704	 * in this app, we expect there to be exactly one.
705	 */
706	SecIdentitySearchRef srchRef = nil;
707	ortn = SecIdentitySearchCreate(kcRef,
708		encryptOnly ? CSSM_KEYUSE_DECRYPT : CSSM_KEYUSE_SIGN,
709		&srchRef);
710	if(ortn) {
711		printf("SecIdentitySearchCreate returned %d.\n", (int)ortn);
712		printf("Cannot find signing key in keychain. Aborting.\n");
713		return nil;
714	}
715	SecIdentityRef identity = nil;
716	ortn = SecIdentitySearchCopyNext(srchRef, &identity);
717	if(ortn) {
718		printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn);
719		printf("Cannot find signing key in keychain. Aborting.\n");
720		return nil;
721	}
722	if(CFGetTypeID(identity) != SecIdentityGetTypeID()) {
723		printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
724		return nil;
725	}
726
727	/*
728	 * Found one.
729	 */
730	if(completeCertChain) {
731		/*
732		 * Place it and the other certs needed to verify it -
733		 * up to but not including the root - in a CFArray.
734		 */
735		SecCertificateRef anchorCert = NULL;
736		if(trustedAnchorFile) {
737			ortn = sslReadAnchor(trustedAnchorFile, &anchorCert);
738			if(ortn) {
739				printf("***Error reading anchor file\n");
740			}
741		}
742		CFArrayRef ca;
743		ortn = sslCompleteCertChain(identity, anchorCert, false, &ca);
744		if(anchorCert) {
745			CFRelease(anchorCert);
746		}
747		return ca;
748	}
749	else {
750		/* simple case, just this one identity */
751		CFArrayRef ca = CFArrayCreate(NULL,
752			(const void **)&identity,
753			1,
754			NULL);
755		if(ca == nil) {
756			printf("CFArrayCreate error\n");
757		}
758		return ca;
759	}
760}
761#endif
762
763OSStatus addTrustedSecCert(
764	SSLContextRef 		ctx,
765	SecCertificateRef 	secCert,
766	bool                replaceAnchors)
767{
768	OSStatus ortn;
769	CFMutableArrayRef array;
770
771	if(secCert == NULL) {
772		printf("***addTrustedSecCert screwup\n");
773		return errSecParam;
774	}
775	array = CFArrayCreateMutable(kCFAllocatorDefault,
776		(CFIndex)1, &kCFTypeArrayCallBacks);
777	if(array == NULL) {
778		return errSecAllocate;
779	}
780	CFArrayAppendValue(array, secCert);
781	ortn = SSLSetTrustedRoots(ctx, array, replaceAnchors ? true : false);
782	if(ortn) {
783		printSslErrStr("SSLSetTrustedRoots", ortn);
784	}
785	CFRelease(array);
786	return ortn;
787}
788
789#if 0
790OSStatus sslReadAnchor(
791	const char 			*anchorFile,
792	SecCertificateRef 	*certRef)
793{
794	OSStatus ortn;
795	SecCertificateRef secCert;
796	unsigned char *certData;
797	unsigned certLen;
798	CSSM_DATA cert;
799
800	if(readFile(anchorFile, &certData, &certLen)) {
801		return -1;
802	}
803	cert.Data = certData;
804	cert.Length = certLen;
805	ortn = SecCertificateCreateFromData(&cert,
806			CSSM_CERT_X_509v3,
807			CSSM_CERT_ENCODING_DER,
808			&secCert);
809	free(certData);
810	if(ortn) {
811		printf("***SecCertificateCreateFromData returned %d\n", (int)ortn);
812		return ortn;
813	}
814	*certRef = secCert;
815	return errSecSuccess;
816}
817#endif
818
819OSStatus sslAddTrustedRoot(
820	SSLContextRef 	ctx,
821	const char 		*anchorFile,
822	bool            replaceAnchors)
823{
824#if 0
825	OSStatus ortn;
826	SecCertificateRef secCert;
827
828	ortn = sslReadAnchor(anchorFile, &secCert);
829	if(ortn) {
830		printf("***Error reading %s. SSLSetTrustedRoots skipped.\n",
831			anchorFile);
832		return ortn;
833	}
834	return addTrustedSecCert(ctx, secCert, replaceAnchors);
835#else
836	return 0;
837#endif
838}
839
840#if 0
841/* Per 3537606 this is no longer necessary */
842/*
843 * Assume incoming identity contains a root (e.g., created by
844 * certtool) and add that cert to ST's trusted anchors. This
845 * enables ST's verify of the incoming chain to succeed without
846 * a kludgy "AllowAnyRoot" specification.
847 */
848OSStatus addIdentityAsTrustedRoot(
849	SSLContextRef 	ctx,
850	CFArrayRef		identArray)
851{
852	CFIndex numItems = CFArrayGetCount(identArray);
853	if(numItems == 0) {
854		printf("***addIdentityAsTrustedRoot: empty identArray\n");
855		return errSecParam;
856	}
857
858	/* Root should be the last item - could be identity, could be cert */
859	CFTypeRef theItem = CFArrayGetValueAtIndex(identArray, numItems - 1);
860	if(CFGetTypeID(theItem) == SecIdentityGetTypeID()) {
861		/* identity */
862		SecCertificateRef certRef;
863		OSStatus ortn = SecIdentityCopyCertificate(
864			(SecIdentityRef)theItem, &certRef);
865		if(ortn) {
866			cssmPerror("SecIdentityCopyCertificate", ortn);
867			printf("***Error gettting cert from identity\n");
868			return ortn;
869		}
870		ortn = addTrustedSecCert(ctx, certRef, false);
871		CFRelease(certRef);
872		return ortn;
873	}
874	else if(CFGetTypeID(theItem) == SecCertificateGetTypeID()) {
875		/* certificate */
876		return addTrustedSecCert(ctx, (SecCertificateRef)theItem, false);
877	}
878	else {
879		printf("***Bogus item in identity array\n");
880		return errSecParam;
881	}
882}
883#else
884OSStatus addIdentityAsTrustedRoot(
885	SSLContextRef 	ctx,
886	CFArrayRef		identArray)
887{
888	return errSecSuccess;
889}
890#endif
891
892/*
893 * Lists of SSLCipherSuites used in sslSetCipherRestrictions. Note that the
894 * SecureTransport library does not implement all of these; we only specify
895 * the ones it claims to support.
896 */
897const SSLCipherSuite suites40[] = {
898	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
899	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
900	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
901	SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
902	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
903	SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
904	SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
905	SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
906	SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
907	SSL_NO_SUCH_CIPHERSUITE
908};
909const SSLCipherSuite suitesDES[] = {
910	SSL_RSA_WITH_DES_CBC_SHA,
911	SSL_DH_DSS_WITH_DES_CBC_SHA,
912	SSL_DH_RSA_WITH_DES_CBC_SHA,
913	SSL_DHE_DSS_WITH_DES_CBC_SHA,
914	SSL_DHE_RSA_WITH_DES_CBC_SHA,
915	SSL_DH_anon_WITH_DES_CBC_SHA,
916	SSL_RSA_WITH_DES_CBC_MD5,
917	SSL_NO_SUCH_CIPHERSUITE
918};
919const SSLCipherSuite suitesDES40[] = {
920	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
921	SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
922	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
923	SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
924	SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
925	SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
926	SSL_NO_SUCH_CIPHERSUITE
927};
928const SSLCipherSuite suites3DES[] = {
929	SSL_RSA_WITH_3DES_EDE_CBC_SHA,
930	SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
931	SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
932	SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
933	SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
934	SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
935	SSL_RSA_WITH_3DES_EDE_CBC_MD5,
936	SSL_NO_SUCH_CIPHERSUITE
937};
938const SSLCipherSuite suitesRC4[] = {
939	SSL_RSA_WITH_RC4_128_MD5,
940	SSL_RSA_WITH_RC4_128_SHA,
941	SSL_DH_anon_WITH_RC4_128_MD5,
942	SSL_NO_SUCH_CIPHERSUITE
943};
944const SSLCipherSuite suitesRC4_40[] = {
945	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
946	SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
947	SSL_NO_SUCH_CIPHERSUITE
948};
949const SSLCipherSuite suitesRC2[] = {
950	SSL_RSA_WITH_RC2_CBC_MD5,
951	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
952	SSL_NO_SUCH_CIPHERSUITE
953};
954const SSLCipherSuite suitesAES128[] = {
955	TLS_RSA_WITH_AES_128_CBC_SHA,
956	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
957	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
958	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
959	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
960	TLS_DH_anon_WITH_AES_128_CBC_SHA,
961    SSL_NO_SUCH_CIPHERSUITE
962};
963const SSLCipherSuite suitesAES256[] = {
964	TLS_RSA_WITH_AES_256_CBC_SHA,
965	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
966	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
967	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
968	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
969	TLS_DH_anon_WITH_AES_256_CBC_SHA,
970    SSL_NO_SUCH_CIPHERSUITE
971};
972const SSLCipherSuite suitesDH[] = {
973    SSL_DH_DSS_WITH_DES_CBC_SHA,
974    SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
975    SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
976    SSL_DH_RSA_WITH_DES_CBC_SHA,
977    SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
978    SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
979    SSL_DHE_DSS_WITH_DES_CBC_SHA,
980    SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
981    SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
982    SSL_DHE_RSA_WITH_DES_CBC_SHA,
983    SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
984    SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
985    SSL_DH_anon_WITH_RC4_128_MD5,
986    SSL_DH_anon_WITH_DES_CBC_SHA,
987    SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
988    SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
989    SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
990	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
991	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
992	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
993	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
994	TLS_DH_anon_WITH_AES_128_CBC_SHA,
995	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
996	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
997	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
998	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
999	TLS_DH_anon_WITH_AES_256_CBC_SHA,
1000	SSL_NO_SUCH_CIPHERSUITE
1001};
1002const SSLCipherSuite suitesDHAnon[] = {
1003    SSL_DH_anon_WITH_RC4_128_MD5,
1004    SSL_DH_anon_WITH_DES_CBC_SHA,
1005    SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
1006    SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
1007    SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
1008	TLS_DH_anon_WITH_AES_128_CBC_SHA,
1009	TLS_DH_anon_WITH_AES_256_CBC_SHA,
1010	SSL_NO_SUCH_CIPHERSUITE
1011};
1012const SSLCipherSuite suitesDH_RSA[] = {
1013    SSL_DH_RSA_WITH_DES_CBC_SHA,
1014    SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
1015    SSL_DHE_RSA_WITH_DES_CBC_SHA,
1016    SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
1017    SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
1018    SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
1019	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
1020	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
1021	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
1022	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
1023	SSL_NO_SUCH_CIPHERSUITE
1024};
1025const SSLCipherSuite suitesDH_DSS[] = {
1026    SSL_DH_DSS_WITH_DES_CBC_SHA,
1027    SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
1028    SSL_DHE_DSS_WITH_DES_CBC_SHA,
1029    SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
1030    SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
1031    SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
1032	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
1033	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
1034	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
1035	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
1036	SSL_NO_SUCH_CIPHERSUITE
1037};
1038const SSLCipherSuite suites_SHA1[] = {
1039	SSL_RSA_WITH_RC4_128_SHA,
1040	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
1041	SSL_RSA_WITH_IDEA_CBC_SHA,
1042	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
1043	SSL_RSA_WITH_DES_CBC_SHA,
1044	SSL_RSA_WITH_3DES_EDE_CBC_SHA,
1045	SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
1046	SSL_DH_DSS_WITH_DES_CBC_SHA,
1047	SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
1048	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
1049	SSL_DH_RSA_WITH_DES_CBC_SHA,
1050	SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
1051	SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
1052	SSL_DHE_DSS_WITH_DES_CBC_SHA,
1053	SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
1054	SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
1055	SSL_DHE_RSA_WITH_DES_CBC_SHA,
1056	SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
1057	SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
1058	SSL_DH_anon_WITH_DES_CBC_SHA,
1059	SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
1060	SSL_FORTEZZA_DMS_WITH_NULL_SHA,
1061	SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,
1062	TLS_RSA_WITH_AES_128_CBC_SHA,
1063	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
1064	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
1065	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
1066	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
1067	TLS_DH_anon_WITH_AES_128_CBC_SHA,
1068	TLS_RSA_WITH_AES_256_CBC_SHA,
1069	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
1070	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
1071	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
1072	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
1073	TLS_DH_anon_WITH_AES_256_CBC_SHA,
1074	SSL_NO_SUCH_CIPHERSUITE
1075};
1076const SSLCipherSuite suites_MD5[] = {
1077	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
1078	SSL_RSA_WITH_RC4_128_MD5,
1079	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
1080	SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
1081	SSL_DH_anon_WITH_RC4_128_MD5,
1082	SSL_NO_SUCH_CIPHERSUITE
1083};
1084
1085
1086/*
1087 * Given an SSLContextRef and an array of SSLCipherSuites, terminated by
1088 * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library
1089 * supports and do a SSLSetEnabledCiphers() specifying those.
1090 */
1091OSStatus sslSetEnabledCiphers(
1092	SSLContextRef ctx,
1093	const SSLCipherSuite *ciphers)
1094{
1095	size_t numSupported;
1096	OSStatus ortn;
1097	SSLCipherSuite *supported = NULL;
1098	SSLCipherSuite *enabled = NULL;
1099	unsigned enabledDex = 0;	// index into enabled
1100	unsigned supportedDex = 0;	// index into supported
1101	unsigned inDex = 0;			// index into ciphers
1102
1103	/* first get all the supported ciphers */
1104	ortn = SSLGetNumberSupportedCiphers(ctx, &numSupported);
1105	if(ortn) {
1106		printSslErrStr("SSLGetNumberSupportedCiphers", ortn);
1107		return ortn;
1108	}
1109	supported = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1110	ortn = SSLGetSupportedCiphers(ctx, supported, &numSupported);
1111	if(ortn) {
1112		printSslErrStr("SSLGetSupportedCiphers", ortn);
1113		return ortn;
1114	}
1115
1116	/*
1117	 * Malloc an array we'll use for SSLGetEnabledCiphers - this will  be
1118	 * bigger than the number of suites we actually specify
1119	 */
1120	enabled = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1121
1122	/*
1123	 * For each valid suite in ciphers, see if it's in the list of
1124	 * supported ciphers. If it is, add it to the list of ciphers to be
1125	 * enabled.
1126	 */
1127	for(inDex=0; ciphers[inDex] != SSL_NO_SUCH_CIPHERSUITE; inDex++) {
1128		for(supportedDex=0; supportedDex<numSupported; supportedDex++) {
1129			if(ciphers[inDex] == supported[supportedDex]) {
1130				enabled[enabledDex++] = ciphers[inDex];
1131				break;
1132			}
1133		}
1134	}
1135
1136	/* send it on down. */
1137	ortn = SSLSetEnabledCiphers(ctx, enabled, enabledDex);
1138	if(ortn) {
1139		printSslErrStr("SSLSetEnabledCiphers", ortn);
1140	}
1141	free(enabled);
1142	free(supported);
1143	return ortn;
1144}
1145
1146/*
1147 * Specify a restricted set of cipherspecs.
1148 */
1149OSStatus sslSetCipherRestrictions(
1150	SSLContextRef ctx,
1151	char cipherRestrict)
1152{
1153	OSStatus ortn;
1154
1155	if(cipherRestrict == '\0') {
1156		return errSecSuccess;		// actually should not have been called
1157	}
1158	switch(cipherRestrict) {
1159		case 'e':
1160			ortn = sslSetEnabledCiphers(ctx, suites40);
1161			break;
1162		case 'd':
1163			ortn = sslSetEnabledCiphers(ctx, suitesDES);
1164			break;
1165		case 'D':
1166			ortn = sslSetEnabledCiphers(ctx, suitesDES40);
1167			break;
1168		case '3':
1169			ortn = sslSetEnabledCiphers(ctx, suites3DES);
1170			break;
1171		case '4':
1172			ortn = sslSetEnabledCiphers(ctx, suitesRC4);
1173			break;
1174		case '$':
1175			ortn = sslSetEnabledCiphers(ctx, suitesRC4_40);
1176			break;
1177		case '2':
1178			ortn = sslSetEnabledCiphers(ctx, suitesRC2);
1179			break;
1180		case 'a':
1181			ortn = sslSetEnabledCiphers(ctx, suitesAES128);
1182			break;
1183		case 'A':
1184			ortn = sslSetEnabledCiphers(ctx, suitesAES256);
1185			break;
1186		case 'h':
1187			ortn = sslSetEnabledCiphers(ctx, suitesDH);
1188			break;
1189		case 'H':
1190			ortn = sslSetEnabledCiphers(ctx, suitesDHAnon);
1191			break;
1192		case 'r':
1193			ortn = sslSetEnabledCiphers(ctx, suitesDH_RSA);
1194			break;
1195		case 's':
1196			ortn = sslSetEnabledCiphers(ctx, suitesDH_DSS);
1197			break;
1198		default:
1199			printf("***bad cipherSpec***\n");
1200			exit(1);
1201	}
1202	return ortn;
1203}
1204
1205#if 0
1206int sslVerifyClientCertState(
1207	char						*whichSide,		// "client" or "server"
1208	SSLClientCertificateState	expectState,
1209	SSLClientCertificateState	gotState)
1210{
1211	if(expectState == SSL_CLIENT_CERT_IGNORE) {
1212		/* app says "don't bopther checking" */
1213		return 0;
1214	}
1215	if(expectState == gotState) {
1216		return 0;
1217	}
1218	printf("***%s: Expected clientCertState %s; got %s\n", whichSide,
1219		sslGetClientCertStateString(expectState),
1220		sslGetClientCertStateString(gotState));
1221	return 1;
1222}
1223
1224int sslVerifyRtn(
1225	char		*whichSide,		// "client" or "server"
1226	OSStatus	expectRtn,
1227	OSStatus	gotRtn)
1228{
1229	if(expectRtn == gotRtn) {
1230		return 0;
1231	}
1232	printf("***%s: Expected return %s; got %s\n", whichSide,
1233		sslGetSSLErrString(expectRtn),
1234		sslGetSSLErrString(gotRtn));
1235	return 1;
1236}
1237
1238int sslVerifyProtVers(
1239	char		*whichSide,		// "client" or "server"
1240	SSLProtocol	expectProt,
1241	SSLProtocol	gotProt)
1242{
1243	if(expectProt == SSL_PROTOCOL_IGNORE) {
1244		/* app says "don't bopther checking" */
1245		return 0;
1246	}
1247	if(expectProt == gotProt) {
1248		return 0;
1249	}
1250	printf("***%s: Expected return %s; got %s\n", whichSide,
1251		sslGetProtocolVersionString(expectProt),
1252		sslGetProtocolVersionString(gotProt));
1253	return 1;
1254}
1255
1256int sslVerifyCipher(
1257	char			*whichSide,		// "client" or "server"
1258	SSLCipherSuite	expectCipher,
1259	SSLCipherSuite	gotCipher)
1260{
1261	if(expectCipher == SSL_CIPHER_IGNORE) {
1262		/* app says "don't bopther checking" */
1263		return 0;
1264	}
1265	if(expectCipher == gotCipher) {
1266		return 0;
1267	}
1268	printf("***%s: Expected return %s; got %s\n", whichSide,
1269		sslGetCipherSuiteString(expectCipher),
1270		sslGetCipherSuiteString(gotCipher));
1271	return 1;
1272}
1273
1274
1275OSStatus sslSetProtocols(
1276	SSLContextRef 	ctx,
1277	const char		*acceptedProts,
1278	SSLProtocol		tryVersion)			// only used if acceptedProts NULL
1279{
1280	OSStatus ortn;
1281
1282	if(acceptedProts) {
1283		#if JAGUAR_BUILD
1284		printf("***SSLSetProtocolVersionEnabled not supported in this config.\n");
1285		exit(1);
1286		#endif
1287		ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false);
1288		if(ortn) {
1289			printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn);
1290			return ortn;
1291		}
1292		for(const char *cp = acceptedProts; *cp; cp++) {
1293			SSLProtocol prot;
1294			switch(*cp) {
1295				case '2':
1296					prot = kSSLProtocol2;
1297					break;
1298				case '3':
1299					prot = kSSLProtocol3;
1300					break;
1301				case 't':
1302					prot = kTLSProtocol1;
1303					break;
1304				default:
1305					printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts);
1306					exit(1);
1307			}
1308			ortn = SSLSetProtocolVersionEnabled(ctx, prot, true);
1309			if(ortn) {
1310				printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
1311				return ortn;
1312			}
1313		}
1314	}
1315	else {
1316		ortn = SSLSetProtocolVersion(ctx, tryVersion);
1317		if(ortn) {
1318			printSslErrStr("SSLSetProtocolVersion", ortn);
1319			return ortn;
1320		}
1321	}
1322	return errSecSuccess;
1323}
1324
1325void sslShowResult(
1326	char				*whichSide,		// "client" or "server"
1327	SslAppTestParams	*params)
1328{
1329	printf("%s status:\n", whichSide);
1330	if(params->acceptedProts) {
1331		printf("   Allowed SSL versions   : %s\n", params->acceptedProts);
1332	}
1333	else {
1334		printf("   Attempted  SSL version : %s\n",
1335			sslGetProtocolVersionString(params->tryVersion));
1336	}
1337	printf("   Result                 : %s\n", sslGetSSLErrString(params->ortn));
1338	printf("   Negotiated SSL version : %s\n",
1339		sslGetProtocolVersionString(params->negVersion));
1340	printf("   Negotiated CipherSuite : %s\n",
1341		sslGetCipherSuiteString(params->negCipher));
1342	if(params->certState != kSSLClientCertNone) {
1343		printf("   Client Cert State      : %s\n",
1344			sslGetClientCertStateString(params->certState));
1345	}
1346}
1347#endif
1348
1349/* print a '.' every few seconds to keep UI alive while connecting */
1350static time_t lastTime = (time_t)0;
1351#define TIME_INTERVAL		3
1352
1353void sslOutputDot()
1354{
1355	time_t thisTime = time(0);
1356
1357	if((thisTime - lastTime) >= TIME_INTERVAL) {
1358		printf("."); fflush(stdout);
1359		lastTime = thisTime;
1360	}
1361}
1362
1363#if 0
1364/* main server pthread body */
1365static void *sslServerThread(void *arg)
1366{
1367	SslAppTestParams *testParams = (SslAppTestParams *)arg;
1368	OSStatus status;
1369
1370	status = sslAppServe(testParams);
1371	pthread_exit((void*)status);
1372	/* NOT REACHED */
1373	return (void *)status;
1374}
1375
1376/*
1377 * Run one session, with the server in a separate thread.
1378 * On entry, serverParams->port is the port we attempt to run on;
1379 * the server thread may overwrite that with a different port if it's
1380 * unable to open the port we specify. Whatever is left in
1381 * serverParams->port is what's used for the client side.
1382 */
1383#define CLIENT_WAIT_SECONDS		1
1384int sslRunSession(
1385	SslAppTestParams*serverParams,
1386	SslAppTestParams *clientParams,
1387	const char 		*testDesc)
1388{
1389	pthread_t serverPthread;
1390	OSStatus clientRtn;
1391	void *serverRtn;
1392
1393	if(testDesc && !clientParams->quiet) {
1394		printf("===== %s =====\n", testDesc);
1395	}
1396
1397	if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) {
1398		printf("***Error initializing mutex; aborting.\n");
1399		return -1;
1400	}
1401	if(pthread_cond_init(&serverParams->pthreadCond, NULL)) {
1402		printf("***Error initializing pthreadCond; aborting.\n");
1403		return -1;
1404	}
1405	serverParams->serverReady = false;		// server sets true
1406
1407	int result = pthread_create(&serverPthread, NULL,
1408			sslServerThread, serverParams);
1409	if(result) {
1410		printf("***Error starting up server thread; aborting.\n");
1411		return result;
1412	}
1413
1414	/* wait for server to set up a socket we can connect to */
1415	if(pthread_mutex_lock(&serverParams->pthreadMutex)) {
1416		printf("***Error acquiring server lock; aborting.\n");
1417		return -1;
1418	}
1419	while(!serverParams->serverReady) {
1420		if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) {
1421			printf("***Error waiting server thread; aborting.\n");
1422			return -1;
1423		}
1424	}
1425	pthread_mutex_unlock(&serverParams->pthreadMutex);
1426	pthread_cond_destroy(&serverParams->pthreadCond);
1427	pthread_mutex_destroy(&serverParams->pthreadMutex);
1428
1429	clientParams->port = serverParams->port;
1430	clientRtn = sslAppClient(clientParams);
1431	/* server doesn't shut down its socket until it sees this */
1432	serverParams->clientDone = 1;
1433	result = pthread_join(serverPthread, &serverRtn);
1434	if(result) {
1435		printf("***pthread_join returned %d, aborting\n", result);
1436		return result;
1437	}
1438
1439	if(serverParams->verbose) {
1440		sslShowResult("server", serverParams);
1441	}
1442	if(clientParams->verbose) {
1443		sslShowResult("client", clientParams);
1444	}
1445
1446	/* verify results */
1447	int ourRtn = 0;
1448	ourRtn += sslVerifyRtn("server", serverParams->expectRtn, serverParams->ortn);
1449	ourRtn += sslVerifyRtn("client", clientParams->expectRtn, clientParams->ortn);
1450	ourRtn += sslVerifyProtVers("server", serverParams->expectVersion,
1451		serverParams->negVersion);
1452	ourRtn += sslVerifyProtVers("client", clientParams->expectVersion,
1453		clientParams->negVersion);
1454	ourRtn += sslVerifyClientCertState("server", serverParams->expectCertState,
1455		serverParams->certState);
1456	ourRtn += sslVerifyClientCertState("client", clientParams->expectCertState,
1457		clientParams->certState);
1458	if(serverParams->ortn == errSecSuccess) {
1459		ourRtn += sslVerifyCipher("server", serverParams->expectCipher,
1460			serverParams->negCipher);
1461	}
1462	if(clientParams->ortn == errSecSuccess) {
1463		ourRtn += sslVerifyCipher("client", clientParams->expectCipher,
1464			clientParams->negCipher);
1465	}
1466	return ourRtn;
1467}
1468
1469static bool isCertRoot(
1470	SecCertificateRef cert)
1471{
1472	/* FIXME - per Radar 3247491, the Sec-level functions we'd like to use for this
1473	 * haven't been written yet...
1474	CSSM_X509_NAME subject;
1475	CSSM_X509_NAME issuer;
1476	OSStatus ortn;
1477	... */
1478	return true;
1479}
1480
1481/*
1482 * Add all of the roots in a given KC to SSL ctx's trusted anchors.
1483 */
1484OSStatus sslAddTrustedRoots(
1485	SSLContextRef 	ctx,
1486	SecKeychainRef	keychain,
1487	bool			*foundOne)		// RETURNED, true if we found
1488									//    at least one root cert
1489{
1490	OSStatus 				ortn;
1491	SecCertificateRef 		secCert;
1492	SecKeychainSearchRef 	srch;
1493
1494	*foundOne = false;
1495	ortn = SecKeychainSearchCreateFromAttributes(keychain,
1496		kSecCertificateItemClass,
1497		NULL,			// any attrs
1498		&srch);
1499	if(ortn) {
1500		printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn);
1501		return ortn;
1502	}
1503
1504	/*
1505	 * Only use root certs. Not an error if we don't find any.
1506	 */
1507	do {
1508		ortn = SecKeychainSearchCopyNext(srch,
1509			(SecKeychainItemRef *)&secCert);
1510		if(ortn) {
1511			break;
1512		}
1513
1514		/* see if it's a root */
1515		if(!isCertRoot(secCert)) {
1516			continue;
1517		}
1518
1519		/* Tell Secure Transport to trust this one. */
1520		ortn = addTrustedSecCert(ctx, secCert, false);
1521		if(ortn) {
1522			/* fatal */
1523			printSslErrStr("addTrustedSecCert", ortn);
1524			return ortn;
1525		}
1526		CFRelease(secCert);
1527		*foundOne = true;
1528	} while(ortn == errSecSuccess);
1529	CFRelease(srch);
1530	return errSecSuccess;
1531}
1532
1533/*
1534 * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename.
1535 */
1536OSStatus sslIdentityPicker(
1537	SecKeychainRef		kcRef,			// NULL means use default list
1538	const char			*trustedAnchor,	// optional additional trusted anchor
1539	bool				includeRoot,	// true --> root is appended to outArray
1540										// false --> root not included
1541	CFArrayRef			*outArray)		// created and RETURNED
1542{
1543	SecCertificateRef trustedCert = NULL;
1544	OSStatus ortn;
1545
1546	if(trustedAnchor) {
1547		ortn = sslReadAnchor(trustedAnchor, &trustedCert);
1548		if(ortn) {
1549			printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n",
1550				trustedAnchor);
1551			trustedCert = NULL;
1552		}
1553	}
1554	ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, outArray);
1555	if(trustedCert) {
1556		CFRelease(trustedCert);
1557	}
1558	return ortn;
1559}
1560
1561/*
1562 * Given a keychain name, convert it into a full path using the "SSL regression
1563 * test suite algorithm". The Sec layer by default locates root root's keychains
1564 * in different places depending on whether we're actually logged in as root
1565 * or running via e.g. cron, so we force the location of root keychains to
1566 * a hard-coded path. User keychain names we leave alone.
1567 */
1568void sslKeychainPath(
1569	const char *kcName,
1570	char *kcPath)			// allocd by caller, MAXPATHLEN
1571{
1572	if(kcName[0] == '\0') {
1573		kcPath[0] = '\0';
1574	}
1575	else if(geteuid() == 0) {
1576		/* root */
1577		sprintf(kcPath, "/Library/Keychains/%s", kcName);
1578	}
1579	else {
1580		/* user, leave alone */
1581		strcpy(kcPath, kcName);
1582	}
1583}
1584
1585/* Verify presence of required file. Returns nonzero if not found. */
1586int sslCheckFile(const char *path)
1587{
1588	struct stat sb;
1589
1590	if(stat(path, &sb)) {
1591		printf("***Can't find file %s.\n", path);
1592		printf("   Try running in the build directory, perhaps after running the\n"
1593			   "   makeLocalCert script.\n");
1594		return 1;
1595	}
1596	return 0;
1597}
1598
1599#endif
1600
1601/* Stringify a SSL_ECDSA_NamedCurve */
1602extern const char *sslCurveString(
1603	SSL_ECDSA_NamedCurve namedCurve)
1604{
1605	static char unk[100];
1606
1607	switch(namedCurve) {
1608		case SSL_Curve_None:	  return "Curve_None";
1609		case SSL_Curve_secp256r1: return "secp256r1";
1610		case SSL_Curve_secp384r1: return "secp384r1";
1611		case SSL_Curve_secp521r1: return "secp521r1";
1612		default:
1613			sprintf(unk, "Unknown <%d>", (int)namedCurve);
1614			return unk;
1615	}
1616}
1617