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