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