]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/sslViewer/sslAppUtils.cpp
Security-55471.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 <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
19 const 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 */
164 const 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 */
186 const 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
282 void printSslErrStr(
283 const char *op,
284 OSStatus err)
285 {
286 printf("*** %s: %s\n", op, sslGetSSLErrString(err));
287 }
288
289 const 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
305 const 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 */
332 CFArrayRef 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
425 errOut:
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
448 errOut:
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 */
466 static 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 }
509 errOut:
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 */
522 OSStatus 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 }
673 errOut:
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 */
696 CFArrayRef 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
772 OSStatus 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
798 OSStatus 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
825 OSStatus 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 */
854 OSStatus 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
890 OSStatus 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 */
903 const 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 };
915 const 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 };
925 const 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 };
934 const 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 };
944 const 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 };
950 const 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 };
955 const SSLCipherSuite suitesRC2[] = {
956 SSL_RSA_WITH_RC2_CBC_MD5,
957 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
958 SSL_NO_SUCH_CIPHERSUITE
959 };
960 const 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 };
969 const 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 };
978 const 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 };
1008 const 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 };
1018 const 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 };
1031 const 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 };
1044 const 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 };
1082 const 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 };
1090 const SSLCipherSuite suites_NULL[] = {
1091 SSL_RSA_WITH_NULL_MD5,
1092 SSL_NO_SUCH_CIPHERSUITE
1093 };
1094
1095 const 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
1107 const 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 */
1124 OSStatus 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 */
1182 OSStatus 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
1248 int 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
1266 int 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
1280 int 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
1298 int 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
1317 OSStatus 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
1363 void 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 */
1388 static CFAbsoluteTime lastTime = (CFAbsoluteTime)0.0;
1389 #define TIME_INTERVAL 3.0
1390
1391 void 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 */
1408 static 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
1427 int 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 */
1515 OSStatus 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 */
1567 OSStatus 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 */
1599 void 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. */
1617 int 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 */
1633 extern 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 }