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