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