2 * Copyright (c) 2006-2008,2010-2013 Apple Inc. All Rights Reserved.
5 #include "sslAppUtils.h"
6 //#include "sslThreading.h"
7 //#include "identPicker.h"
8 //#include <utilLib/common.h>
11 #include <sys/param.h>
12 #include <Security/SecBase.h>
14 #include <CoreFoundation/CoreFoundation.h>
15 #include <Security/Security.h>
16 #include <Security/SecIdentityPriv.h>
17 #include <AssertMacros.h>
20 #include "utilities/SecCFRelease.h"
22 /* Set true when PR-3074739 is merged to TOT */
23 #define NEW_SSL_ERRS_3074739 1
26 const char *sslGetCipherSuiteString(SSLCipherSuite cs
)
28 static char noSuite
[40];
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";
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";
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";
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";
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";
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";
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";
153 * Tags for SSL 2 cipher kinds which are not specified for SSL 3.
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";
162 snprintf(noSuite
, sizeof(noSuite
), "Unknown ciphersuite 0x%04x", (unsigned)cs
);
168 * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion -
169 * return a string representation.
171 const char *sslGetProtocolVersionString(SSLProtocol prot
)
173 static char noProt
[20];
175 #pragma clang diagnostic push
176 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
178 case kSSLProtocolUnknown
:
179 return "kSSLProtocolUnknown";
181 return "kSSLProtocol2";
183 return "kSSLProtocol3";
184 case kSSLProtocol3Only
:
185 return "kSSLProtocol3Only";
187 return "kTLSProtocol1";
188 case kTLSProtocol1Only
:
189 return "kTLSProtocol1Only";
191 return "kTLSProtocol11";
193 return "kTLSProtocol12";
195 sprintf(noProt
, "Unknown (%d)", (unsigned)prot
);
198 #pragma clang diagnostic pop
202 * Return string representation of SecureTransport-related OSStatus.
204 const char *sslGetSSLErrString(OSStatus err
)
206 static char errSecSuccessStr
[20];
210 return "errSecSuccess";
212 return "errSecAllocate";
214 return "errSecParam";
215 case errSecUnimplemented
:
216 return "errSecUnimplemented";
220 return "errSecBadReq";
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";
238 return "errSSLBadCert";
240 return "errSSLCrypto";
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";
317 /* some from the Sec layer */
318 case errSecNotAvailable
: return "errSecNotAvailable";
319 case errSecDuplicateItem
: return "errSecDuplicateItem";
320 case errSecItemNotFound
: return "errSecItemNotFound";
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";
331 if (err
< (CSSM_BASE_ERROR
+
332 (CSSM_ERRORCODE_MODULE_EXTENT
* 8)))
334 /* assume CSSM error */
335 return cssmErrToStr(err
);
340 sprintf(errSecSuccessStr
, "Unknown (%d)", (unsigned)err
);
341 return errSecSuccessStr
;
350 printf("*** %s: %s\n", op
, sslGetSSLErrString(err
));
353 const char *sslGetClientCertStateString(SSLClientCertificateState state
)
355 static char noState
[20];
357 #pragma clang diagnostic push
358 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
360 case kSSLClientCertNone
:
361 return "ClientCertNone";
362 case kSSLClientCertRequested
:
363 return "CertRequested";
364 case kSSLClientCertSent
:
365 return "ClientCertSent";
366 case kSSLClientCertRejected
:
367 return "ClientCertRejected";
369 sprintf(noState
, "Unknown (%d)", (unsigned)state
);
372 #pragma clang diagnostic pop
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.
383 CFArrayRef
getSslCerts(
384 const char *kcName
, // may be NULL, i.e., use default
386 bool completeCertChain
,
387 const char *anchorFile
, // optional trusted anchor
388 SecKeychainRef
*pKcRef
) // RETURNED
391 SecKeychainRef kcRef
= nil
;
396 /* pick a keychain */
398 ortn
= SecKeychainOpen(kcName
, &kcRef
);
400 printf("SecKeychainOpen returned %d.\n", (int)ortn
);
401 printf("Cannot open keychain at %s. Aborting.\n", kcName
);
406 /* use default keychain */
407 ortn
= SecKeychainCopyDefault(&kcRef
);
409 printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn
);
414 return sslKcRefToCertArray(kcRef
, encryptOnly
, completeCertChain
, anchorFile
);
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
;
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
),
433 require(key
= (SecKeyRef
)CFDictionaryGetValue(keyResult
, kSecValueRef
),
435 require(pkdigest
= CFDictionaryGetValue(keyResult
, kSecAttrApplicationLabel
),
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
);
446 // Create an identity from the key and certificate.
447 require(identity
= SecIdentityCreate(NULL
, cert
, key
), errOut
);
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
),
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
);
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
466 require(result
= CFArrayCreateMutable(NULL
, certCount
, &kCFTypeArrayCallBacks
),
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
));
477 CFReleaseSafe(trust
);
478 CFReleaseSafe(certificates
);
479 CFReleaseSafe(identity
);
481 CFReleaseSafe(certQuery
);
482 CFReleaseSafe(keyResult
);
483 CFReleaseSafe(keyQuery
);
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.
495 * Returns true if the cert appears to be a root.
497 static bool isCertRefRoot(
498 SecCertificateRef certRef
)
502 /* just search for the two attrs we want */
503 UInt32 tags
[2] = {kSecSubjectItemAttr
, kSecIssuerItemAttr
};
504 SecKeychainAttributeInfo attrInfo
;
507 attrInfo
.format
= NULL
;
508 SecKeychainAttributeList
*attrList
= NULL
;
509 SecKeychainAttribute
*attr1
= NULL
;
510 SecKeychainAttribute
*attr2
= NULL
;
512 OSStatus ortn
= SecKeychainItemCopyAttributesAndData(
513 (SecKeychainItemRef
)certRef
,
517 NULL
, // length - don't need the data
520 cssmPerror("SecKeychainItemCopyAttributesAndData", ortn
);
521 /* may want to be a bit more robust here, but this should
525 /* subsequent errors to errOut: */
527 if((attrList
== NULL
) || (attrList
->count
!= 2)) {
528 printf("***Unexpected result fetching label attr\n");
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) {
541 SecKeychainItemFreeAttributesAndData(attrList
, NULL
);
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().
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
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
568 certArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
569 CFArrayAppendValue(certArray
, identity
);
572 * Case 1: identity is a root; we're done. Note that this case
573 * overrides the includeRoot argument.
575 SecCertificateRef certRef
;
576 OSStatus ortn
= SecIdentityCopyCertificate(identity
, &certRef
);
578 /* should never happen */
579 cssmPerror("SecIdentityCopyCertificate", ortn
);
582 bool isRoot
= isCertRefRoot(certRef
);
584 *outArray
= certArray
;
586 return errSecSuccess
;
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.)
595 CFMutableArrayRef subjCerts
= CFArrayCreateMutable(NULL
, 1, &kCFTypeArrayCallBacks
);
596 CFArraySetValueAtIndex(subjCerts
, 0, certRef
);
598 /* the array owns the subject cert ref now */
601 /* Get a SecPolicyRef for generic X509 cert chain verification */
602 ortn
= SecPolicySearchCreate(CSSM_CERT_X_509v3
,
603 &CSSMOID_APPLE_X509_BASIC
,
607 cssmPerror("SecPolicySearchCreate", ortn
);
610 ortn
= SecPolicySearchCopyNext(policySearch
, &policy
);
612 cssmPerror("SecPolicySearchCopyNext", ortn
);
616 /* build a SecTrustRef for specified policy and certs */
617 ortn
= SecTrustCreateWithCertificates(subjCerts
,
620 cssmPerror("SecTrustCreateWithCertificates", ortn
);
626 * Tell SecTrust to trust this one in addition to the current
627 * trusted system-wide anchors.
629 CFMutableArrayRef newAnchors
;
630 CFArrayRef currAnchors
;
632 ortn
= SecTrustCopyAnchorCertificates(&currAnchors
);
634 /* should never happen */
635 cssmPerror("SecTrustCopyAnchorCertificates", ortn
);
638 newAnchors
= CFArrayCreateMutableCopy(NULL
,
639 CFArrayGetCount(currAnchors
) + 1,
641 CFRelease(currAnchors
);
642 CFArrayAppendValue(newAnchors
, trustedAnchor
);
643 ortn
= SecTrustSetAnchorCertificates(secTrust
, newAnchors
);
644 CFRelease(newAnchors
);
646 cssmPerror("SecTrustSetAnchorCertificates", ortn
);
651 ortn
= SecTrustEvaluate(secTrust
, &secTrustResult
);
653 cssmPerror("SecTrustEvaluate", ortn
);
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 */
664 * Cert chain construction failed.
665 * Just go with the single subject cert we were given.
667 printf("***Warning: could not construct completed cert chain\n");
668 ortn
= errSecSuccess
;
672 /* get resulting constructed cert chain */
673 ortn
= SecTrustGetResult(secTrust
, &secTrustResult
, &certChain
, &dummyEv
);
675 cssmPerror("SecTrustEvaluate", ortn
);
680 * Copy certs from constructed chain to our result array, skipping
681 * the leaf (which is already there, as a SecIdentityRef) and possibly
684 numResCerts
= CFArrayGetCount(certChain
);
685 if(numResCerts
< 2) {
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().
691 printf("***sslCompleteCertChain screwup: numResCerts %d\n",
693 ortn
= errSecSuccess
;
697 /* skip the last (root) cert) */
700 for(CFIndex dex
=1; dex
<numResCerts
; dex
++) {
701 certRef
= (SecCertificateRef
)CFArrayGetValueAtIndex(certChain
, dex
);
702 CFArrayAppendValue(certArray
, certRef
);
710 CFRelease(subjCerts
);
716 CFRelease(policySearch
);
718 *outArray
= certArray
;
724 * Given an open keychain, find a SecIdentityRef and munge it into
725 * a CFArrayRef required by SSLSetCertificate().
727 CFArrayRef
sslKcRefToCertArray(
728 SecKeychainRef kcRef
,
730 bool completeCertChain
,
731 const char *trustedAnchorFile
)
733 /* quick check to make sure the keychain exists */
734 SecKeychainStatus kcStat
;
735 OSStatus ortn
= SecKeychainGetStatus(kcRef
, &kcStat
);
737 printSslErrStr("SecKeychainGetStatus", ortn
);
738 printf("Can not open keychain. Aborting.\n");
743 * Search for "any" identity matching specified key use;
744 * in this app, we expect there to be exactly one.
746 SecIdentitySearchRef srchRef
= nil
;
747 ortn
= SecIdentitySearchCreate(kcRef
,
748 encryptOnly
? CSSM_KEYUSE_DECRYPT
: CSSM_KEYUSE_SIGN
,
751 printf("SecIdentitySearchCreate returned %d.\n", (int)ortn
);
752 printf("Cannot find signing key in keychain. Aborting.\n");
755 SecIdentityRef identity
= nil
;
756 ortn
= SecIdentitySearchCopyNext(srchRef
, &identity
);
758 printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn
);
759 printf("Cannot find signing key in keychain. Aborting.\n");
762 if(CFGetTypeID(identity
) != SecIdentityGetTypeID()) {
763 printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
770 if(completeCertChain
) {
772 * Place it and the other certs needed to verify it -
773 * up to but not including the root - in a CFArray.
775 SecCertificateRef anchorCert
= NULL
;
776 if(trustedAnchorFile
) {
777 ortn
= sslReadAnchor(trustedAnchorFile
, &anchorCert
);
779 printf("***Error reading anchor file\n");
783 ortn
= sslCompleteCertChain(identity
, anchorCert
, false, &ca
);
785 CFRelease(anchorCert
);
790 /* simple case, just this one identity */
791 CFArrayRef ca
= CFArrayCreate(NULL
,
792 (const void **)&identity
,
796 printf("CFArrayCreate error\n");
803 #pragma clang diagnostic push
804 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
806 OSStatus
addTrustedSecCert(
808 SecCertificateRef secCert
,
812 CFMutableArrayRef array
;
814 if(secCert
== NULL
) {
815 printf("***addTrustedSecCert screwup\n");
818 array
= CFArrayCreateMutable(kCFAllocatorDefault
,
819 (CFIndex
)1, &kCFTypeArrayCallBacks
);
821 return errSecAllocate
;
823 CFArrayAppendValue(array
, secCert
);
824 ortn
= SSLSetTrustedRoots(ctx
, array
, replaceAnchors
? true : false);
826 printSslErrStr("SSLSetTrustedRoots", ortn
);
832 #pragma clang diagnostic pop
834 OSStatus
sslAddTrustedRoot(
836 const char *anchorFile
,
842 OSStatus
addIdentityAsTrustedRoot(
844 CFArrayRef identArray
)
846 return errSecSuccess
;
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
1048 OSStatus
sslSetEnabledCiphers(
1050 const SSLCipherSuite
*ciphers
)
1052 size_t numSupported
;
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
1060 /* first get all the supported ciphers */
1061 #pragma clang diagnostic push
1062 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1063 ortn
= SSLGetNumberSupportedCiphers(ctx
, &numSupported
);
1065 printSslErrStr("SSLGetNumberSupportedCiphers", ortn
);
1068 supported
= (SSLCipherSuite
*)malloc(numSupported
* sizeof(SSLCipherSuite
));
1069 ortn
= SSLGetSupportedCiphers(ctx
, supported
, &numSupported
);
1071 printSslErrStr("SSLGetSupportedCiphers", ortn
);
1076 * Malloc an array we'll use for SSLGetEnabledCiphers - this will be
1077 * bigger than the number of suites we actually specify
1079 enabled
= (SSLCipherSuite
*)malloc(numSupported
* sizeof(SSLCipherSuite
));
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
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
];
1095 /* send it on down. */
1096 ortn
= SSLSetEnabledCiphers(ctx
, enabled
, enabledDex
);
1098 printSslErrStr("SSLSetEnabledCiphers", ortn
);
1100 #pragma clang diagnostic pop
1107 * Specify a restricted set of cipherspecs.
1109 OSStatus
sslSetCipherRestrictions(
1111 char cipherRestrict
)
1115 if(cipherRestrict
== '\0') {
1116 return errSecSuccess
; // actually should not have been called
1118 switch(cipherRestrict
) {
1120 ortn
= sslSetEnabledCiphers(ctx
, suites40
);
1123 ortn
= sslSetEnabledCiphers(ctx
, suitesDES
);
1126 ortn
= sslSetEnabledCiphers(ctx
, suitesDES40
);
1129 ortn
= sslSetEnabledCiphers(ctx
, suites3DES
);
1132 ortn
= sslSetEnabledCiphers(ctx
, suitesRC4
);
1135 ortn
= sslSetEnabledCiphers(ctx
, suitesRC4_40
);
1138 ortn
= sslSetEnabledCiphers(ctx
, suitesRC2
);
1141 ortn
= sslSetEnabledCiphers(ctx
, suitesAES128
);
1144 ortn
= sslSetEnabledCiphers(ctx
, suitesAES256
);
1147 ortn
= sslSetEnabledCiphers(ctx
, suitesDH
);
1150 ortn
= sslSetEnabledCiphers(ctx
, suitesDHAnon
);
1153 ortn
= sslSetEnabledCiphers(ctx
, suitesDH_RSA
);
1156 ortn
= sslSetEnabledCiphers(ctx
, suitesDH_DSS
);
1159 printf("***bad cipherSpec***\n");
1166 int sslVerifyClientCertState(
1167 char *whichSide
, // "client" or "server"
1168 SSLClientCertificateState expectState
,
1169 SSLClientCertificateState gotState
)
1171 if(expectState
== SSL_CLIENT_CERT_IGNORE
) {
1172 /* app says "don't bopther checking" */
1175 if(expectState
== gotState
) {
1178 printf("***%s: Expected clientCertState %s; got %s\n", whichSide
,
1179 sslGetClientCertStateString(expectState
),
1180 sslGetClientCertStateString(gotState
));
1185 char *whichSide
, // "client" or "server"
1189 if(expectRtn
== gotRtn
) {
1192 printf("***%s: Expected return %s; got %s\n", whichSide
,
1193 sslGetSSLErrString(expectRtn
),
1194 sslGetSSLErrString(gotRtn
));
1198 int sslVerifyProtVers(
1199 char *whichSide
, // "client" or "server"
1200 SSLProtocol expectProt
,
1201 SSLProtocol gotProt
)
1203 if(expectProt
== SSL_PROTOCOL_IGNORE
) {
1204 /* app says "don't bopther checking" */
1207 if(expectProt
== gotProt
) {
1210 printf("***%s: Expected return %s; got %s\n", whichSide
,
1211 sslGetProtocolVersionString(expectProt
),
1212 sslGetProtocolVersionString(gotProt
));
1216 int sslVerifyCipher(
1217 char *whichSide
, // "client" or "server"
1218 SSLCipherSuite expectCipher
,
1219 SSLCipherSuite gotCipher
)
1221 if(expectCipher
== SSL_CIPHER_IGNORE
) {
1222 /* app says "don't bopther checking" */
1225 if(expectCipher
== gotCipher
) {
1228 printf("***%s: Expected return %s; got %s\n", whichSide
,
1229 sslGetCipherSuiteString(expectCipher
),
1230 sslGetCipherSuiteString(gotCipher
));
1235 OSStatus
sslSetProtocols(
1237 const char *acceptedProts
,
1238 SSLProtocol tryVersion
) // only used if acceptedProts NULL
1244 printf("***SSLSetProtocolVersionEnabled not supported in this config.\n");
1247 ortn
= SSLSetProtocolVersionEnabled(ctx
, kSSLProtocolAll
, false);
1249 printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn
);
1252 for(const char *cp
= acceptedProts
; *cp
; cp
++) {
1256 prot
= kSSLProtocol2
;
1259 prot
= kSSLProtocol3
;
1262 prot
= kTLSProtocol1
;
1265 printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts
);
1268 ortn
= SSLSetProtocolVersionEnabled(ctx
, prot
, true);
1270 printSslErrStr("SSLSetProtocolVersionEnabled", ortn
);
1276 ortn
= SSLSetProtocolVersion(ctx
, tryVersion
);
1278 printSslErrStr("SSLSetProtocolVersion", ortn
);
1282 return errSecSuccess
;
1286 char *whichSide
, // "client" or "server"
1287 SslAppTestParams
*params
)
1289 printf("%s status:\n", whichSide
);
1290 if(params
->acceptedProts
) {
1291 printf(" Allowed SSL versions : %s\n", params
->acceptedProts
);
1294 printf(" Attempted SSL version : %s\n",
1295 sslGetProtocolVersionString(params
->tryVersion
));
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
));
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
1315 time_t thisTime
= time(0);
1317 if((thisTime
- lastTime
) >= TIME_INTERVAL
) {
1318 printf("."); fflush(stdout
);
1319 lastTime
= thisTime
;
1324 /* main server pthread body */
1325 static void *sslServerThread(void *arg
)
1327 SslAppTestParams
*testParams
= (SslAppTestParams
*)arg
;
1330 status
= sslAppServe(testParams
);
1331 pthread_exit((void*)status
);
1333 return (void *)status
;
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.
1343 #define CLIENT_WAIT_SECONDS 1
1345 SslAppTestParams
*serverParams
,
1346 SslAppTestParams
*clientParams
,
1347 const char *testDesc
)
1349 pthread_t serverPthread
;
1353 if(testDesc
&& !clientParams
->quiet
) {
1354 printf("===== %s =====\n", testDesc
);
1357 if(pthread_mutex_init(&serverParams
->pthreadMutex
, NULL
)) {
1358 printf("***Error initializing mutex; aborting.\n");
1361 if(pthread_cond_init(&serverParams
->pthreadCond
, NULL
)) {
1362 printf("***Error initializing pthreadCond; aborting.\n");
1365 serverParams
->serverReady
= false; // server sets true
1367 int result
= pthread_create(&serverPthread
, NULL
,
1368 sslServerThread
, serverParams
);
1370 printf("***Error starting up server thread; aborting.\n");
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");
1379 while(!serverParams
->serverReady
) {
1380 if(pthread_cond_wait(&serverParams
->pthreadCond
, &serverParams
->pthreadMutex
)) {
1381 printf("***Error waiting server thread; aborting.\n");
1385 pthread_mutex_unlock(&serverParams
->pthreadMutex
);
1386 pthread_cond_destroy(&serverParams
->pthreadCond
);
1387 pthread_mutex_destroy(&serverParams
->pthreadMutex
);
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
);
1395 printf("***pthread_join returned %d, aborting\n", result
);
1399 if(serverParams
->verbose
) {
1400 sslShowResult("server", serverParams
);
1402 if(clientParams
->verbose
) {
1403 sslShowResult("client", clientParams
);
1406 /* verify results */
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
);
1422 if(clientParams
->ortn
== errSecSuccess
) {
1423 ourRtn
+= sslVerifyCipher("client", clientParams
->expectCipher
,
1424 clientParams
->negCipher
);
1429 static bool isCertRoot(
1430 SecCertificateRef cert
)
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;
1442 * Add all of the roots in a given KC to SSL ctx's trusted anchors.
1444 OSStatus
sslAddTrustedRoots(
1446 SecKeychainRef keychain
,
1447 bool *foundOne
) // RETURNED, true if we found
1448 // at least one root cert
1451 SecCertificateRef secCert
;
1452 SecKeychainSearchRef srch
;
1455 ortn
= SecKeychainSearchCreateFromAttributes(keychain
,
1456 kSecCertificateItemClass
,
1460 printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn
);
1465 * Only use root certs. Not an error if we don't find any.
1468 ortn
= SecKeychainSearchCopyNext(srch
,
1469 (SecKeychainItemRef
*)&secCert
);
1474 /* see if it's a root */
1475 if(!isCertRoot(secCert
)) {
1479 /* Tell Secure Transport to trust this one. */
1480 ortn
= addTrustedSecCert(ctx
, secCert
, false);
1483 printSslErrStr("addTrustedSecCert", ortn
);
1488 } while(ortn
== errSecSuccess
);
1490 return errSecSuccess
;
1494 * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename.
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
1503 SecCertificateRef trustedCert
= NULL
;
1507 ortn
= sslReadAnchor(trustedAnchor
, &trustedCert
);
1509 printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n",
1514 ortn
= sslIdentPicker(kcRef
, trustedCert
, includeRoot
, outArray
);
1516 CFRelease(trustedCert
);
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.
1528 void sslKeychainPath(
1530 char *kcPath
) // allocd by caller, MAXPATHLEN
1532 if(kcName
[0] == '\0') {
1535 else if(geteuid() == 0) {
1537 sprintf(kcPath
, "/Library/Keychains/%s", kcName
);
1540 /* user, leave alone */
1541 strcpy(kcPath
, kcName
);
1545 /* Verify presence of required file. Returns nonzero if not found. */
1546 int sslCheckFile(const char *path
)
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");
1561 /* Stringify a SSL_ECDSA_NamedCurve */
1562 extern const char *sslCurveString(
1563 SSL_ECDSA_NamedCurve namedCurve
)
1565 static char unk
[100];
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";
1573 sprintf(unk
, "Unknown <%d>", (int)namedCurve
);
1581 #include <Security/SecCertificatePriv.h>
1582 #include <Security/SecKey.h>
1584 SecKeyRef
create_private_key_from_der(bool ecdsa
, const unsigned char *pkey_der
, size_t pkey_der_len
)
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
);
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
)
1601 SecKeyRef pkey
= NULL
;
1602 SecCertificateRef cert
= NULL
;
1603 SecIdentityRef ident
= NULL
;
1604 CFArrayRef items
= NULL
;
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
);
1612 CFReleaseSafe(pkey
);
1613 CFReleaseSafe(cert
);
1614 CFReleaseSafe(ident
);