2 #include "sslAppUtils.h"
3 #include "sslThreading.h"
4 #include "identPicker.h"
5 #include <utilLib/fileIo.h>
6 #include <utilLib/common.h>
10 #include <sys/types.h>
12 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
13 #include <Security/AuthSession.h> // for Sec errors
14 #include <CoreFoundation/CFDate.h>
16 /* Set true when PR-3074739 is merged to TOT */
17 #define NEW_SSL_ERRS_3074739 1
19 const char *sslGetCipherSuiteString(SSLCipherSuite cs
)
21 static char noSuite
[40];
24 case SSL_NULL_WITH_NULL_NULL
:
25 return "SSL_NULL_WITH_NULL_NULL";
26 case SSL_RSA_WITH_NULL_MD5
:
27 return "SSL_RSA_WITH_NULL_MD5";
28 case SSL_RSA_WITH_NULL_SHA
:
29 return "SSL_RSA_WITH_NULL_SHA";
30 case SSL_RSA_EXPORT_WITH_RC4_40_MD5
:
31 return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
32 case SSL_RSA_WITH_RC4_128_MD5
:
33 return "SSL_RSA_WITH_RC4_128_MD5";
34 case SSL_RSA_WITH_RC4_128_SHA
:
35 return "SSL_RSA_WITH_RC4_128_SHA";
36 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
:
37 return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
38 case SSL_RSA_WITH_IDEA_CBC_SHA
:
39 return "SSL_RSA_WITH_IDEA_CBC_SHA";
40 case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
:
41 return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
42 case SSL_RSA_WITH_DES_CBC_SHA
:
43 return "SSL_RSA_WITH_DES_CBC_SHA";
44 case SSL_RSA_WITH_3DES_EDE_CBC_SHA
:
45 return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
46 case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
:
47 return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
48 case SSL_DH_DSS_WITH_DES_CBC_SHA
:
49 return "SSL_DH_DSS_WITH_DES_CBC_SHA";
50 case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
:
51 return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
52 case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
:
53 return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
54 case SSL_DH_RSA_WITH_DES_CBC_SHA
:
55 return "SSL_DH_RSA_WITH_DES_CBC_SHA";
56 case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
:
57 return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
58 case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
:
59 return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
60 case SSL_DHE_DSS_WITH_DES_CBC_SHA
:
61 return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
62 case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
:
63 return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
64 case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
:
65 return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
66 case SSL_DHE_RSA_WITH_DES_CBC_SHA
:
67 return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
68 case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
:
69 return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
70 case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
:
71 return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
72 case SSL_DH_anon_WITH_RC4_128_MD5
:
73 return "SSL_DH_anon_WITH_RC4_128_MD5";
74 case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
:
75 return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
76 case SSL_DH_anon_WITH_DES_CBC_SHA
:
77 return "SSL_DH_anon_WITH_DES_CBC_SHA";
78 case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
:
79 return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
80 case SSL_FORTEZZA_DMS_WITH_NULL_SHA
:
81 return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
82 case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA
:
83 return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
84 case SSL_RSA_WITH_RC2_CBC_MD5
:
85 return "SSL_RSA_WITH_RC2_CBC_MD5";
86 case SSL_RSA_WITH_IDEA_CBC_MD5
:
87 return "SSL_RSA_WITH_IDEA_CBC_MD5";
88 case SSL_RSA_WITH_DES_CBC_MD5
:
89 return "SSL_RSA_WITH_DES_CBC_MD5";
90 case SSL_RSA_WITH_3DES_EDE_CBC_MD5
:
91 return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
92 case SSL_NO_SUCH_CIPHERSUITE
:
93 return "SSL_NO_SUCH_CIPHERSUITE";
94 case TLS_RSA_WITH_AES_128_CBC_SHA
:
95 return "TLS_RSA_WITH_AES_128_CBC_SHA";
96 case TLS_DH_DSS_WITH_AES_128_CBC_SHA
:
97 return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
98 case TLS_DH_RSA_WITH_AES_128_CBC_SHA
:
99 return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
100 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA
:
101 return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
102 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA
:
103 return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
104 case TLS_DH_anon_WITH_AES_128_CBC_SHA
:
105 return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
106 case TLS_RSA_WITH_AES_256_CBC_SHA
:
107 return "TLS_RSA_WITH_AES_256_CBC_SHA";
108 case TLS_DH_DSS_WITH_AES_256_CBC_SHA
:
109 return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
110 case TLS_DH_RSA_WITH_AES_256_CBC_SHA
:
111 return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
112 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA
:
113 return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
114 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA
:
115 return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
116 case TLS_DH_anon_WITH_AES_256_CBC_SHA
:
117 return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
120 case TLS_ECDH_ECDSA_WITH_NULL_SHA
:
121 return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
122 case TLS_ECDH_ECDSA_WITH_RC4_128_SHA
:
123 return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
124 case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
:
125 return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
126 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
:
127 return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
128 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
:
129 return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
130 case TLS_ECDHE_ECDSA_WITH_NULL_SHA
:
131 return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
132 case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
:
133 return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
134 case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
:
135 return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
136 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
:
137 return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
138 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
:
139 return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
140 case TLS_ECDH_RSA_WITH_NULL_SHA
:
141 return "TLS_ECDH_RSA_WITH_NULL_SHA";
142 case TLS_ECDH_RSA_WITH_RC4_128_SHA
:
143 return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
144 case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
:
145 return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
146 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
:
147 return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
148 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
:
149 return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
150 case TLS_ECDHE_RSA_WITH_NULL_SHA
:
151 return "TLS_ECDHE_RSA_WITH_NULL_SHA";
152 case TLS_ECDHE_RSA_WITH_RC4_128_SHA
:
153 return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
154 case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
:
155 return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
156 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
:
157 return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
158 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
:
159 return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
160 case TLS_ECDH_anon_WITH_NULL_SHA
:
161 return "TLS_ECDH_anon_WITH_NULL_SHA";
162 case TLS_ECDH_anon_WITH_RC4_128_SHA
:
163 return "TLS_ECDH_anon_WITH_RC4_128_SHA";
164 case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
:
165 return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
166 case TLS_ECDH_anon_WITH_AES_128_CBC_SHA
:
167 return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
168 case TLS_ECDH_anon_WITH_AES_256_CBC_SHA
:
169 return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
172 sprintf(noSuite
, "Unknown (%d)", (unsigned)cs
);
178 * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion -
179 * return a string representation.
181 const char *sslGetProtocolVersionString(SSLProtocol prot
)
183 static char noProt
[20];
186 case kSSLProtocolUnknown
:
187 return "kSSLProtocolUnknown";
189 return "kSSLProtocol2";
191 return "kSSLProtocol3";
192 case kSSLProtocol3Only
:
193 return "kSSLProtocol3Only";
195 return "kTLSProtocol1";
196 case kTLSProtocol1Only
:
197 return "kTLSProtocol1Only";
199 sprintf(noProt
, "Unknown (%d)", (unsigned)prot
);
205 * Return string representation of SecureTransport-related OSStatus.
207 const char *sslGetSSLErrString(OSStatus err
)
209 static char noErrStr
[20];
225 return "errSSLProtocol";
226 case errSSLNegotiation
:
227 return "errSSLNegotiation";
228 case errSSLFatalAlert
:
229 return "errSSLFatalAlert";
230 case errSSLWouldBlock
:
231 return "errSSLWouldBlock";
232 case errSSLSessionNotFound
:
233 return "errSSLSessionNotFound";
234 case errSSLClosedGraceful
:
235 return "errSSLClosedGraceful";
236 case errSSLClosedAbort
:
237 return "errSSLClosedAbort";
238 case errSSLXCertChainInvalid
:
239 return "errSSLXCertChainInvalid";
241 return "errSSLBadCert";
243 return "errSSLCrypto";
245 return "errSSLInternal";
246 case errSSLModuleAttach
:
247 return "errSSLModuleAttach";
248 case errSSLUnknownRootCert
:
249 return "errSSLUnknownRootCert";
250 case errSSLNoRootCert
:
251 return "errSSLNoRootCert";
252 case errSSLCertExpired
:
253 return "errSSLCertExpired";
254 case errSSLCertNotYetValid
:
255 return "errSSLCertNotYetValid";
256 case errSSLClosedNoNotify
:
257 return "errSSLClosedNoNotify";
258 case errSSLBufferOverflow
:
259 return "errSSLBufferOverflow";
260 case errSSLBadCipherSuite
:
261 return "errSSLBadCipherSuite";
262 /* TLS/Panther addenda */
263 case errSSLPeerUnexpectedMsg
:
264 return "errSSLPeerUnexpectedMsg";
265 case errSSLPeerBadRecordMac
:
266 return "errSSLPeerBadRecordMac";
267 case errSSLPeerDecryptionFail
:
268 return "errSSLPeerDecryptionFail";
269 case errSSLPeerRecordOverflow
:
270 return "errSSLPeerRecordOverflow";
271 case errSSLPeerDecompressFail
:
272 return "errSSLPeerDecompressFail";
273 case errSSLPeerHandshakeFail
:
274 return "errSSLPeerHandshakeFail";
275 case errSSLPeerBadCert
:
276 return "errSSLPeerBadCert";
277 case errSSLPeerUnsupportedCert
:
278 return "errSSLPeerUnsupportedCert";
279 case errSSLPeerCertRevoked
:
280 return "errSSLPeerCertRevoked";
281 case errSSLPeerCertExpired
:
282 return "errSSLPeerCertExpired";
283 case errSSLPeerCertUnknown
:
284 return "errSSLPeerCertUnknown";
285 case errSSLIllegalParam
:
286 return "errSSLIllegalParam";
287 case errSSLPeerUnknownCA
:
288 return "errSSLPeerUnknownCA";
289 case errSSLPeerAccessDenied
:
290 return "errSSLPeerAccessDenied";
291 case errSSLPeerDecodeError
:
292 return "errSSLPeerDecodeError";
293 case errSSLPeerDecryptError
:
294 return "errSSLPeerDecryptError";
295 case errSSLPeerExportRestriction
:
296 return "errSSLPeerExportRestriction";
297 case errSSLPeerProtocolVersion
:
298 return "errSSLPeerProtocolVersion";
299 case errSSLPeerInsufficientSecurity
:
300 return "errSSLPeerInsufficientSecurity";
301 case errSSLPeerInternalError
:
302 return "errSSLPeerInternalError";
303 case errSSLPeerUserCancelled
:
304 return "errSSLPeerUserCancelled";
305 case errSSLPeerNoRenegotiation
:
306 return "errSSLPeerNoRenegotiation";
307 case errSSLHostNameMismatch
:
308 return "errSSLHostNameMismatch";
309 case errSSLConnectionRefused
:
310 return "errSSLConnectionRefused";
311 case errSSLDecryptionFail
:
312 return "errSSLDecryptionFail";
313 case errSSLBadRecordMac
:
314 return "errSSLBadRecordMac";
315 case errSSLRecordOverflow
:
316 return "errSSLRecordOverflow";
317 case errSSLBadConfiguration
:
318 return "errSSLBadConfiguration";
320 /* some from the Sec layer */
321 case errSecNotAvailable
: return "errSecNotAvailable";
322 case errSecReadOnly
: return "errSecReadOnly";
323 case errSecAuthFailed
: return "errSecAuthFailed";
324 case errSecNoSuchKeychain
: return "errSecNoSuchKeychain";
325 case errSecInvalidKeychain
: return "errSecInvalidKeychain";
326 case errSecDuplicateItem
: return "errSecDuplicateItem";
327 case errSecItemNotFound
: return "errSecItemNotFound";
328 case errSecNoSuchAttr
: return "errSecNoSuchAttr";
329 case errSecInvalidItemRef
: return "errSecInvalidItemRef";
330 case errSecInvalidSearchRef
: return "errSecInvalidSearchRef";
331 case errSecNoSuchClass
: return "errSecNoSuchClass";
332 case errSecNoDefaultKeychain
: return "errSecNoDefaultKeychain";
333 case errSecWrongSecVersion
: return "errSecWrongSecVersion";
334 case errSessionInvalidId
: return "errSessionInvalidId";
335 case errSessionInvalidAttributes
: return "errSessionInvalidAttributes";
336 case errSessionAuthorizationDenied
: return "errSessionAuthorizationDenied";
337 case errSessionInternal
: return "errSessionInternal";
338 case errSessionInvalidFlags
: return "errSessionInvalidFlags";
339 case errSecInvalidTrustSettings
: return "errSecInvalidTrustSettings";
340 case errSecNoTrustSettings
: return "errSecNoTrustSettings";
343 if(err
< (CSSM_BASE_ERROR
+
344 (CSSM_ERRORCODE_MODULE_EXTENT
* 8))) {
345 /* assume CSSM error */
346 return cssmErrToStr(err
);
349 sprintf(noErrStr
, "Unknown (%d)", (unsigned)err
);
359 printf("*** %s: %s\n", op
, sslGetSSLErrString(err
));
362 const char *sslGetClientCertStateString(SSLClientCertificateState state
)
364 static char noState
[20];
367 case kSSLClientCertNone
:
368 return "ClientCertNone";
369 case kSSLClientCertRequested
:
370 return "CertRequested";
371 case kSSLClientCertSent
:
372 return "ClientCertSent";
373 case kSSLClientCertRejected
:
374 return "ClientCertRejected";
376 sprintf(noState
, "Unknown (%d)", (unsigned)state
);
382 const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType
)
384 static char noType
[20];
387 case SSLClientAuthNone
:
389 case SSLClientAuth_RSASign
:
391 case SSLClientAuth_DSSSign
:
393 case SSLClientAuth_RSAFixedDH
:
395 case SSLClientAuth_DSS_FixedDH
:
396 return "DSS_FixedDH";
397 case SSLClientAuth_ECDSASign
:
399 case SSLClientAuth_RSAFixedECDH
:
400 return "RSAFixedECDH";
401 case SSLClientAuth_ECDSAFixedECDH
:
402 return "ECDSAFixedECDH";
404 sprintf(noType
, "Unknown (%d)", (unsigned)authType
);
410 * Convert a keychain name (which may be NULL) into the CFArrayRef required
411 * by SSLSetCertificate. This is a bare-bones example of this operation,
412 * since it requires and assumes that there is exactly one SecIdentity
413 * in the keychain - i.e., there is exactly one matching cert/private key
414 * pair. A real world server would probably search a keychain for a SecIdentity
415 * matching some specific criteria.
417 CFArrayRef
getSslCerts(
418 const char *kcName
, // may be NULL, i.e., use default
419 CSSM_BOOL encryptOnly
,
420 CSSM_BOOL completeCertChain
,
421 const char *anchorFile
, // optional trusted anchor
422 SecKeychainRef
*pKcRef
) // RETURNED
424 SecKeychainRef kcRef
= nil
;
429 /* pick a keychain */
431 ortn
= SecKeychainOpen(kcName
, &kcRef
);
433 printf("SecKeychainOpen returned %d.\n", (int)ortn
);
434 printf("Cannot open keychain at %s. Aborting.\n", kcName
);
439 /* use default keychain */
440 ortn
= SecKeychainCopyDefault(&kcRef
);
442 printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn
);
447 return sslKcRefToCertArray(kcRef
, encryptOnly
, completeCertChain
,
453 * Determine if specified SecCertificateRef is a self-signed cert.
454 * We do this by comparing the subject and issuerr names; no cryptographic
455 * verification is performed.
457 * Returns true if the cert appears to be a root.
459 static bool isCertRefRoot(
460 SecCertificateRef certRef
)
462 /* just search for the two attrs we want */
463 UInt32 tags
[2] = {kSecSubjectItemAttr
, kSecIssuerItemAttr
};
464 SecKeychainAttributeInfo attrInfo
;
467 attrInfo
.format
= NULL
;
468 SecKeychainAttributeList
*attrList
= NULL
;
469 SecKeychainAttribute
*attr1
= NULL
;
470 SecKeychainAttribute
*attr2
= NULL
;
473 OSStatus ortn
= SecKeychainItemCopyAttributesAndData(
474 (SecKeychainItemRef
)certRef
,
478 NULL
, // length - don't need the data
481 cssmPerror("SecKeychainItemCopyAttributesAndData", ortn
);
482 /* may want to be a bit more robust here, but this should
486 /* subsequent errors to errOut: */
488 if((attrList
== NULL
) || (attrList
->count
!= 2)) {
489 printf("***Unexpected result fetching label attr\n");
493 /* rootness is just byte-for-byte compare of the two names */
494 attr1
= &attrList
->attr
[0];
495 attr2
= &attrList
->attr
[1];
496 if(attr1
->length
== attr2
->length
) {
497 if(memcmp(attr1
->data
, attr2
->data
, attr1
->length
) == 0) {
502 SecKeychainItemFreeAttributesAndData(attrList
, NULL
);
508 * Given a SecIdentityRef, do our best to construct a complete, ordered, and
509 * verified cert chain, returning the result in a CFArrayRef. The result is
510 * suitable for use when calling SSLSetCertificate().
512 OSStatus
sslCompleteCertChain(
513 SecIdentityRef identity
,
514 SecCertificateRef trustedAnchor
, // optional additional trusted anchor
515 bool includeRoot
, // include the root in outArray
516 const CSSM_OID
*vfyPolicy
, // optional - if NULL, use SSL
517 CFArrayRef
*outArray
) // created and RETURNED
519 CFMutableArrayRef certArray
;
520 SecTrustRef secTrust
= NULL
;
521 SecPolicyRef policy
= NULL
;
522 SecPolicySearchRef policySearch
= NULL
;
523 SecTrustResultType secTrustResult
;
524 CSSM_TP_APPLE_EVIDENCE_INFO
*dummyEv
; // not used
525 CFArrayRef certChain
= NULL
; // constructed chain
528 certArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
529 CFArrayAppendValue(certArray
, identity
);
532 * Case 1: identity is a root; we're done. Note that this case
533 * overrides the includeRoot argument.
535 SecCertificateRef certRef
;
536 OSStatus ortn
= SecIdentityCopyCertificate(identity
, &certRef
);
538 /* should never happen */
539 cssmPerror("SecIdentityCopyCertificate", ortn
);
542 bool isRoot
= isCertRefRoot(certRef
);
544 *outArray
= certArray
;
550 * Now use SecTrust to get a complete cert chain, using all of the
551 * user's keychains to look for intermediate certs.
552 * NOTE this does NOT handle root certs which are not in the system
553 * root cert DB. (The above case, where the identity is a root cert, does.)
555 CFMutableArrayRef subjCerts
= CFArrayCreateMutable(NULL
, 1, &kCFTypeArrayCallBacks
);
556 CFArraySetValueAtIndex(subjCerts
, 0, certRef
);
558 /* the array owns the subject cert ref now */
561 /* Get a SecPolicyRef for SSL cert chain verification */
562 ortn
= SecPolicySearchCreate(CSSM_CERT_X_509v3
,
563 vfyPolicy
? vfyPolicy
: &CSSMOID_APPLE_TP_SSL
,
567 cssmPerror("SecPolicySearchCreate", ortn
);
570 ortn
= SecPolicySearchCopyNext(policySearch
, &policy
);
572 cssmPerror("SecPolicySearchCopyNext", ortn
);
576 /* build a SecTrustRef for specified policy and certs */
577 ortn
= SecTrustCreateWithCertificates(subjCerts
,
580 cssmPerror("SecTrustCreateWithCertificates", ortn
);
586 * Tell SecTrust to trust this one in addition to the current
587 * trusted system-wide anchors.
589 CFMutableArrayRef newAnchors
;
590 CFArrayRef currAnchors
;
592 ortn
= SecTrustCopyAnchorCertificates(&currAnchors
);
594 /* should never happen */
595 cssmPerror("SecTrustCopyAnchorCertificates", ortn
);
598 newAnchors
= CFArrayCreateMutableCopy(NULL
,
599 CFArrayGetCount(currAnchors
) + 1,
601 CFRelease(currAnchors
);
602 CFArrayAppendValue(newAnchors
, trustedAnchor
);
603 ortn
= SecTrustSetAnchorCertificates(secTrust
, newAnchors
);
604 CFRelease(newAnchors
);
606 cssmPerror("SecTrustSetAnchorCertificates", ortn
);
611 ortn
= SecTrustEvaluate(secTrust
, &secTrustResult
);
613 cssmPerror("SecTrustEvaluate", ortn
);
616 switch(secTrustResult
) {
617 case kSecTrustResultUnspecified
:
618 /* cert chain valid, no special UserTrust assignments */
619 case kSecTrustResultProceed
:
620 /* cert chain valid AND user explicitly trusts this */
624 * Cert chain construction failed.
625 * Just go with the single subject cert we were given.
627 printf("***Warning: could not construct completed cert chain\n");
632 /* get resulting constructed cert chain */
633 ortn
= SecTrustGetResult(secTrust
, &secTrustResult
, &certChain
, &dummyEv
);
635 cssmPerror("SecTrustEvaluate", ortn
);
640 * Copy certs from constructed chain to our result array, skipping
641 * the leaf (which is already there, as a SecIdentityRef) and possibly
644 numResCerts
= CFArrayGetCount(certChain
);
645 if(numResCerts
< 2) {
647 * Can't happen: if subject was a root, we'd already have returned.
648 * If chain doesn't verify to a root, we'd have bailed after
649 * SecTrustEvaluate().
651 printf("***sslCompleteCertChain screwup: numResCerts %d\n",
657 /* skip the last (root) cert) */
660 for(CFIndex dex
=1; dex
<numResCerts
; dex
++) {
661 certRef
= (SecCertificateRef
)CFArrayGetValueAtIndex(certChain
, dex
);
662 CFArrayAppendValue(certArray
, certRef
);
670 CFRelease(subjCerts
);
676 CFRelease(policySearch
);
678 *outArray
= certArray
;
684 * Given an open keychain, find a SecIdentityRef and munge it into
685 * a CFArrayRef required by SSLSetCertificate().
687 CFArrayRef
sslKcRefToCertArray(
688 SecKeychainRef kcRef
,
689 CSSM_BOOL encryptOnly
,
690 CSSM_BOOL completeCertChain
,
691 const CSSM_OID
*vfyPolicy
, // optional - if NULL, use SSL policy to complete
692 const char *trustedAnchorFile
)
694 /* quick check to make sure the keychain exists */
695 SecKeychainStatus kcStat
;
696 OSStatus ortn
= SecKeychainGetStatus(kcRef
, &kcStat
);
698 printSslErrStr("SecKeychainGetStatus", ortn
);
699 printf("Can not open keychain. Aborting.\n");
704 * Search for "any" identity matching specified key use;
705 * in this app, we expect there to be exactly one.
707 SecIdentitySearchRef srchRef
= nil
;
708 ortn
= SecIdentitySearchCreate(kcRef
,
709 encryptOnly
? CSSM_KEYUSE_DECRYPT
: CSSM_KEYUSE_SIGN
,
712 printf("SecIdentitySearchCreate returned %d.\n", (int)ortn
);
713 printf("Cannot find signing key in keychain. Aborting.\n");
716 SecIdentityRef identity
= nil
;
717 ortn
= SecIdentitySearchCopyNext(srchRef
, &identity
);
719 printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn
);
720 printf("Cannot find signing key in keychain. Aborting.\n");
723 if(CFGetTypeID(identity
) != SecIdentityGetTypeID()) {
724 printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
731 if(completeCertChain
) {
733 * Place it and the other certs needed to verify it -
734 * up to but not including the root - in a CFArray.
736 SecCertificateRef anchorCert
= NULL
;
737 if(trustedAnchorFile
) {
738 ortn
= sslReadAnchor(trustedAnchorFile
, &anchorCert
);
740 printf("***Error reading anchor file\n");
744 ortn
= sslCompleteCertChain(identity
, anchorCert
, false, vfyPolicy
, &ca
);
746 CFRelease(anchorCert
);
751 /* simple case, just this one identity */
752 CFArrayRef ca
= CFArrayCreate(NULL
,
753 (const void **)&identity
,
757 printf("CFArrayCreate error\n");
763 OSStatus
addTrustedSecCert(
765 SecCertificateRef secCert
,
766 CSSM_BOOL replaceAnchors
)
769 CFMutableArrayRef array
;
771 if(secCert
== NULL
) {
772 printf("***addTrustedSecCert screwup\n");
775 array
= CFArrayCreateMutable(kCFAllocatorDefault
,
776 (CFIndex
)1, &kCFTypeArrayCallBacks
);
780 CFArrayAppendValue(array
, secCert
);
781 ortn
= SSLSetTrustedRoots(ctx
, array
, replaceAnchors
? true : false);
783 printSslErrStr("SSLSetTrustedRoots", ortn
);
789 OSStatus
sslReadAnchor(
790 const char *anchorFile
,
791 SecCertificateRef
*certRef
)
794 SecCertificateRef secCert
;
795 unsigned char *certData
;
800 rtn
= cspReadFile(anchorFile
, &certData
, &certLen
);
802 printf("cspReadFile(%s) returned %d\n", anchorFile
, rtn
);
805 cert
.Data
= certData
;
806 cert
.Length
= certLen
;
807 ortn
= SecCertificateCreateFromData(&cert
,
809 CSSM_CERT_ENCODING_DER
,
813 printf("***SecCertificateCreateFromData returned %d\n", (int)ortn
);
820 OSStatus
sslAddTrustedRoot(
822 const char *anchorFile
,
823 CSSM_BOOL replaceAnchors
)
826 SecCertificateRef secCert
;
828 ortn
= sslReadAnchor(anchorFile
, &secCert
);
830 printf("***Error (%ld) reading %s. SSLSetTrustedRoots skipped.\n",
831 (long)ortn
, anchorFile
);
834 return addTrustedSecCert(ctx
, secCert
, replaceAnchors
);
838 /* Per 3537606 this is no longer necessary */
840 * Assume incoming identity contains a root (e.g., created by
841 * certtool) and add that cert to ST's trusted anchors. This
842 * enables ST's verify of the incoming chain to succeed without
843 * a kludgy "AllowAnyRoot" specification.
845 OSStatus
addIdentityAsTrustedRoot(
847 CFArrayRef identArray
)
849 CFIndex numItems
= CFArrayGetCount(identArray
);
851 printf("***addIdentityAsTrustedRoot: empty identArray\n");
855 /* Root should be the last item - could be identity, could be cert */
856 CFTypeRef theItem
= CFArrayGetValueAtIndex(identArray
, numItems
- 1);
857 if(CFGetTypeID(theItem
) == SecIdentityGetTypeID()) {
859 SecCertificateRef certRef
;
860 OSStatus ortn
= SecIdentityCopyCertificate(
861 (SecIdentityRef
)theItem
, &certRef
);
863 cssmPerror("SecIdentityCopyCertificate", ortn
);
864 printf("***Error gettting cert from identity\n");
867 ortn
= addTrustedSecCert(ctx
, certRef
, CSSM_FALSE
);
871 else if(CFGetTypeID(theItem
) == SecCertificateGetTypeID()) {
873 return addTrustedSecCert(ctx
, (SecCertificateRef
)theItem
, CSSM_FALSE
);
876 printf("***Bogus item in identity array\n");
881 OSStatus
addIdentityAsTrustedRoot(
883 CFArrayRef identArray
)
890 * Lists of SSLCipherSuites used in sslSetCipherRestrictions. Note that the
891 * SecureTransport library does not implement all of these; we only specify
892 * the ones it claims to support.
894 const SSLCipherSuite suites40
[] = {
895 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
896 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
897 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
898 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
899 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
900 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
901 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
902 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
903 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
904 SSL_NO_SUCH_CIPHERSUITE
906 const SSLCipherSuite suitesDES
[] = {
907 SSL_RSA_WITH_DES_CBC_SHA
,
908 SSL_DH_DSS_WITH_DES_CBC_SHA
,
909 SSL_DH_RSA_WITH_DES_CBC_SHA
,
910 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
911 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
912 SSL_DH_anon_WITH_DES_CBC_SHA
,
913 SSL_RSA_WITH_DES_CBC_MD5
,
914 SSL_NO_SUCH_CIPHERSUITE
916 const SSLCipherSuite suitesDES40
[] = {
917 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
918 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
919 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
920 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
921 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
922 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
923 SSL_NO_SUCH_CIPHERSUITE
925 const SSLCipherSuite suites3DES
[] = {
926 SSL_RSA_WITH_3DES_EDE_CBC_SHA
,
927 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
928 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
929 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
930 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
931 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
932 SSL_RSA_WITH_3DES_EDE_CBC_MD5
,
933 SSL_NO_SUCH_CIPHERSUITE
935 const SSLCipherSuite suitesRC4
[] = {
936 SSL_RSA_WITH_RC4_128_MD5
,
937 SSL_RSA_WITH_RC4_128_SHA
,
938 SSL_DH_anon_WITH_RC4_128_MD5
,
939 SSL_NO_SUCH_CIPHERSUITE
941 const SSLCipherSuite suitesRC4_40
[] = {
942 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
943 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
944 SSL_NO_SUCH_CIPHERSUITE
946 const SSLCipherSuite suitesRC2
[] = {
947 SSL_RSA_WITH_RC2_CBC_MD5
,
948 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
949 SSL_NO_SUCH_CIPHERSUITE
951 const SSLCipherSuite suitesAES128
[] = {
952 TLS_RSA_WITH_AES_128_CBC_SHA
,
953 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
954 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
955 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
956 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
957 TLS_DH_anon_WITH_AES_128_CBC_SHA
959 const SSLCipherSuite suitesAES256
[] = {
960 TLS_RSA_WITH_AES_256_CBC_SHA
,
961 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
962 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
963 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
964 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
965 TLS_DH_anon_WITH_AES_256_CBC_SHA
967 const SSLCipherSuite suitesDH
[] = {
968 SSL_DH_DSS_WITH_DES_CBC_SHA
,
969 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
970 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
971 SSL_DH_RSA_WITH_DES_CBC_SHA
,
972 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
973 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
974 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
975 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
976 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
977 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
978 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
979 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
980 SSL_DH_anon_WITH_RC4_128_MD5
,
981 SSL_DH_anon_WITH_DES_CBC_SHA
,
982 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
983 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
984 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
985 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
986 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
987 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
988 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
989 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
990 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
991 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
992 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
993 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
994 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
995 SSL_NO_SUCH_CIPHERSUITE
997 const SSLCipherSuite suitesDHAnon
[] = {
998 SSL_DH_anon_WITH_RC4_128_MD5
,
999 SSL_DH_anon_WITH_DES_CBC_SHA
,
1000 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
1001 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
1002 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
1003 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
1004 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
1005 SSL_NO_SUCH_CIPHERSUITE
1007 const SSLCipherSuite suitesDH_RSA
[] = {
1008 SSL_DH_RSA_WITH_DES_CBC_SHA
,
1009 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
1010 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
1011 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
1012 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1013 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1014 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
1015 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
1016 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
1017 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
1018 SSL_NO_SUCH_CIPHERSUITE
1020 const SSLCipherSuite suitesDH_DSS
[] = {
1021 SSL_DH_DSS_WITH_DES_CBC_SHA
,
1022 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
1023 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
1024 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
1025 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1026 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1027 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
1028 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
1029 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
1030 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
1031 SSL_NO_SUCH_CIPHERSUITE
1033 const SSLCipherSuite suites_SHA1
[] = {
1034 SSL_RSA_WITH_RC4_128_SHA
,
1035 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1036 SSL_RSA_WITH_IDEA_CBC_SHA
,
1037 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1038 SSL_RSA_WITH_DES_CBC_SHA
,
1039 SSL_RSA_WITH_3DES_EDE_CBC_SHA
,
1040 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1041 SSL_DH_DSS_WITH_DES_CBC_SHA
,
1042 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
1043 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1044 SSL_DH_RSA_WITH_DES_CBC_SHA
,
1045 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
1046 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1047 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
1048 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
1049 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1050 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
1051 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
1052 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
1053 SSL_DH_anon_WITH_DES_CBC_SHA
,
1054 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
1055 SSL_FORTEZZA_DMS_WITH_NULL_SHA
,
1056 SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA
,
1057 TLS_RSA_WITH_AES_128_CBC_SHA
,
1058 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
1059 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
1060 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
1061 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
1062 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
1063 TLS_RSA_WITH_AES_256_CBC_SHA
,
1064 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
1065 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
1066 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
1067 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
1068 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
1069 SSL_NO_SUCH_CIPHERSUITE
1071 const SSLCipherSuite suites_MD5
[] = {
1072 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
1073 SSL_RSA_WITH_RC4_128_MD5
,
1074 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
1075 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
1076 SSL_DH_anon_WITH_RC4_128_MD5
,
1077 SSL_NO_SUCH_CIPHERSUITE
1079 const SSLCipherSuite suites_NULL
[] = {
1080 SSL_RSA_WITH_NULL_MD5
,
1081 SSL_NO_SUCH_CIPHERSUITE
1084 const SSLCipherSuite suites_ECDHE
[] = {
1085 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
,
1086 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
,
1087 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
,
1088 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
,
1089 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
,
1090 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
,
1091 TLS_ECDHE_RSA_WITH_RC4_128_SHA
,
1092 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
,
1093 SSL_NO_SUCH_CIPHERSUITE
1096 const SSLCipherSuite suites_ECDH
[] = {
1097 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
,
1098 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
,
1099 TLS_ECDH_ECDSA_WITH_RC4_128_SHA
,
1100 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
,
1101 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
,
1102 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
,
1103 TLS_ECDH_RSA_WITH_RC4_128_SHA
,
1104 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
,
1105 SSL_NO_SUCH_CIPHERSUITE
1110 * Given an SSLContextRef and an array of SSLCipherSuites, terminated by
1111 * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library
1112 * supports and do a SSLSetEnabledCiphers() specifying those.
1114 OSStatus
sslSetEnabledCiphers(
1116 const SSLCipherSuite
*ciphers
)
1118 size_t numSupported
;
1120 SSLCipherSuite
*supported
= NULL
;
1121 SSLCipherSuite
*enabled
= NULL
;
1122 unsigned enabledDex
= 0; // index into enabled
1123 unsigned supportedDex
= 0; // index into supported
1124 unsigned inDex
= 0; // index into ciphers
1126 /* first get all the supported ciphers */
1127 ortn
= SSLGetNumberSupportedCiphers(ctx
, &numSupported
);
1129 printSslErrStr("SSLGetNumberSupportedCiphers", ortn
);
1132 supported
= (SSLCipherSuite
*)malloc(numSupported
* sizeof(SSLCipherSuite
));
1133 ortn
= SSLGetSupportedCiphers(ctx
, supported
, &numSupported
);
1135 printSslErrStr("SSLGetSupportedCiphers", ortn
);
1140 * Malloc an array we'll use for SSLGetEnabledCiphers - this will be
1141 * bigger than the number of suites we actually specify
1143 enabled
= (SSLCipherSuite
*)malloc(numSupported
* sizeof(SSLCipherSuite
));
1146 * For each valid suite in ciphers, see if it's in the list of
1147 * supported ciphers. If it is, add it to the list of ciphers to be
1150 for(inDex
=0; ciphers
[inDex
] != SSL_NO_SUCH_CIPHERSUITE
; inDex
++) {
1151 for(supportedDex
=0; supportedDex
<numSupported
; supportedDex
++) {
1152 if(ciphers
[inDex
] == supported
[supportedDex
]) {
1153 enabled
[enabledDex
++] = ciphers
[inDex
];
1159 /* send it on down. */
1160 ortn
= SSLSetEnabledCiphers(ctx
, enabled
, enabledDex
);
1162 printSslErrStr("SSLSetEnabledCiphers", ortn
);
1170 * Specify a restricted set of cipherspecs.
1172 OSStatus
sslSetCipherRestrictions(
1174 char cipherRestrict
)
1178 if(cipherRestrict
== '\0') {
1179 return noErr
; // actually should not have been called
1181 switch(cipherRestrict
) {
1183 ortn
= sslSetEnabledCiphers(ctx
, suites40
);
1186 ortn
= sslSetEnabledCiphers(ctx
, suitesDES
);
1189 ortn
= sslSetEnabledCiphers(ctx
, suitesDES40
);
1192 ortn
= sslSetEnabledCiphers(ctx
, suites3DES
);
1195 ortn
= sslSetEnabledCiphers(ctx
, suitesRC4
);
1198 ortn
= sslSetEnabledCiphers(ctx
, suitesRC4_40
);
1201 ortn
= sslSetEnabledCiphers(ctx
, suitesRC2
);
1204 ortn
= sslSetEnabledCiphers(ctx
, suitesAES128
);
1207 ortn
= sslSetEnabledCiphers(ctx
, suitesAES256
);
1210 ortn
= sslSetEnabledCiphers(ctx
, suitesDH
);
1213 ortn
= sslSetEnabledCiphers(ctx
, suitesDHAnon
);
1216 ortn
= sslSetEnabledCiphers(ctx
, suitesDH_RSA
);
1219 ortn
= sslSetEnabledCiphers(ctx
, suitesDH_DSS
);
1222 ortn
= sslSetEnabledCiphers(ctx
, suites_NULL
);
1225 ortn
= sslSetEnabledCiphers(ctx
, suites_ECDHE
);
1228 ortn
= sslSetEnabledCiphers(ctx
, suites_ECDH
);
1231 printf("***bad cipherSpec***\n");
1237 int sslVerifyClientCertState(
1238 const char *whichSide
, // "client" or "server"
1239 SSLClientCertificateState expectState
,
1240 SSLClientCertificateState gotState
)
1242 if(expectState
== SSL_CLIENT_CERT_IGNORE
) {
1243 /* app says "don't bother checking" */
1246 if(expectState
== gotState
) {
1249 printf("***%s: Expected clientCertState %s; got %s\n", whichSide
,
1250 sslGetClientCertStateString(expectState
),
1251 sslGetClientCertStateString(gotState
));
1256 const char *whichSide
, // "client" or "server"
1260 if(expectRtn
== gotRtn
) {
1263 printf("***%s: Expected return %s; got %s\n", whichSide
,
1264 sslGetSSLErrString(expectRtn
),
1265 sslGetSSLErrString(gotRtn
));
1269 int sslVerifyProtVers(
1270 const char *whichSide
, // "client" or "server"
1271 SSLProtocol expectProt
,
1272 SSLProtocol gotProt
)
1274 if(expectProt
== SSL_PROTOCOL_IGNORE
) {
1275 /* app says "don't bopther checking" */
1278 if(expectProt
== gotProt
) {
1281 printf("***%s: Expected return %s; got %s\n", whichSide
,
1282 sslGetProtocolVersionString(expectProt
),
1283 sslGetProtocolVersionString(gotProt
));
1287 int sslVerifyCipher(
1288 const char *whichSide
, // "client" or "server"
1289 SSLCipherSuite expectCipher
,
1290 SSLCipherSuite gotCipher
)
1292 if(expectCipher
== SSL_CIPHER_IGNORE
) {
1293 /* app says "don't bopther checking" */
1296 if(expectCipher
== gotCipher
) {
1299 printf("***%s: Expected return %s; got %s\n", whichSide
,
1300 sslGetCipherSuiteString(expectCipher
),
1301 sslGetCipherSuiteString(gotCipher
));
1306 OSStatus
sslSetProtocols(
1308 const char *acceptedProts
,
1309 SSLProtocol tryVersion
) // only used if acceptedProts NULL
1314 ortn
= SSLSetProtocolVersionEnabled(ctx
, kSSLProtocolAll
, false);
1316 printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn
);
1319 for(const char *cp
= acceptedProts
; *cp
; cp
++) {
1323 prot
= kSSLProtocol2
;
1326 prot
= kSSLProtocol3
;
1329 prot
= kTLSProtocol1
;
1332 printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts
);
1335 ortn
= SSLSetProtocolVersionEnabled(ctx
, prot
, true);
1337 printSslErrStr("SSLSetProtocolVersionEnabled", ortn
);
1343 ortn
= SSLSetProtocolVersion(ctx
, tryVersion
);
1345 printSslErrStr("SSLSetProtocolVersion", ortn
);
1353 const char *whichSide
, // "client" or "server"
1354 SslAppTestParams
*params
)
1356 printf("%s status:\n", whichSide
);
1357 if(params
->acceptedProts
) {
1358 printf(" Allowed SSL versions : %s\n", params
->acceptedProts
);
1361 printf(" Attempted SSL version : %s\n",
1362 sslGetProtocolVersionString(params
->tryVersion
));
1364 printf(" Result : %s\n", sslGetSSLErrString(params
->ortn
));
1365 printf(" Negotiated SSL version : %s\n",
1366 sslGetProtocolVersionString(params
->negVersion
));
1367 printf(" Negotiated CipherSuite : %s\n",
1368 sslGetCipherSuiteString(params
->negCipher
));
1369 if(params
->certState
!= kSSLClientCertNone
) {
1370 printf(" Client Cert State : %s\n",
1371 sslGetClientCertStateString(params
->certState
));
1375 /* print a '.' every few seconds to keep UI alive while connecting */
1376 static CFAbsoluteTime lastTime
= (CFAbsoluteTime
)0.0;
1377 #define TIME_INTERVAL 3.0
1381 CFAbsoluteTime thisTime
= CFAbsoluteTimeGetCurrent();
1383 if(lastTime
== 0.0) {
1384 /* avoid printing first time thru */
1385 lastTime
= thisTime
;
1388 if((thisTime
- lastTime
) >= TIME_INTERVAL
) {
1389 printf("."); fflush(stdout
);
1390 lastTime
= thisTime
;
1394 /* main server pthread body */
1395 static void *sslServerThread(void *arg
)
1397 SslAppTestParams
*testParams
= (SslAppTestParams
*)arg
;
1400 status
= sslAppServe(testParams
);
1401 pthread_exit((void*)status
);
1403 return (void *)status
;
1407 * Run one session, with the server in a separate thread.
1408 * On entry, serverParams->port is the port we attempt to run on;
1409 * the server thread may overwrite that with a different port if it's
1410 * unable to open the port we specify. Whatever is left in
1411 * serverParams->port is what's used for the client side.
1413 #define CLIENT_WAIT_SECONDS 1
1415 SslAppTestParams
*serverParams
,
1416 SslAppTestParams
*clientParams
,
1417 const char *testDesc
)
1419 pthread_t serverPthread
;
1423 if(testDesc
&& !clientParams
->quiet
) {
1424 printf("===== %s =====\n", testDesc
);
1428 * Workaround for Radar 4619502: resolve references to Security.framework
1429 * here, in main thread, before we fork off the server thread.
1431 SecKeychainRef defaultKc
= NULL
;
1432 SecKeychainCopyDefault(&defaultKc
);
1433 /* end workaround */
1435 if(pthread_mutex_init(&serverParams
->pthreadMutex
, NULL
)) {
1436 printf("***Error initializing mutex; aborting.\n");
1439 if(pthread_cond_init(&serverParams
->pthreadCond
, NULL
)) {
1440 printf("***Error initializing pthreadCond; aborting.\n");
1443 serverParams
->serverReady
= false; // server sets true
1445 int result
= pthread_create(&serverPthread
, NULL
,
1446 sslServerThread
, serverParams
);
1448 printf("***Error starting up server thread; aborting.\n");
1452 /* wait for server to set up a socket we can connect to */
1453 if(pthread_mutex_lock(&serverParams
->pthreadMutex
)) {
1454 printf("***Error acquiring server lock; aborting.\n");
1457 while(!serverParams
->serverReady
) {
1458 if(pthread_cond_wait(&serverParams
->pthreadCond
, &serverParams
->pthreadMutex
)) {
1459 printf("***Error waiting server thread; aborting.\n");
1463 pthread_mutex_unlock(&serverParams
->pthreadMutex
);
1464 pthread_cond_destroy(&serverParams
->pthreadCond
);
1465 pthread_mutex_destroy(&serverParams
->pthreadMutex
);
1467 clientParams
->port
= serverParams
->port
;
1468 clientRtn
= sslAppClient(clientParams
);
1469 /* server doesn't shut down its socket until it sees this */
1470 serverParams
->clientDone
= 1;
1471 result
= pthread_join(serverPthread
, &serverRtn
);
1473 printf("***pthread_join returned %d, aborting\n", result
);
1477 if(serverParams
->verbose
) {
1478 sslShowResult("server", serverParams
);
1480 if(clientParams
->verbose
) {
1481 sslShowResult("client", clientParams
);
1484 /* verify results */
1486 ourRtn
+= sslVerifyRtn("server", serverParams
->expectRtn
, serverParams
->ortn
);
1487 ourRtn
+= sslVerifyRtn("client", clientParams
->expectRtn
, clientParams
->ortn
);
1488 ourRtn
+= sslVerifyProtVers("server", serverParams
->expectVersion
,
1489 serverParams
->negVersion
);
1490 ourRtn
+= sslVerifyProtVers("client", clientParams
->expectVersion
,
1491 clientParams
->negVersion
);
1492 ourRtn
+= sslVerifyClientCertState("server", serverParams
->expectCertState
,
1493 serverParams
->certState
);
1494 ourRtn
+= sslVerifyClientCertState("client", clientParams
->expectCertState
,
1495 clientParams
->certState
);
1496 if(serverParams
->ortn
== noErr
) {
1497 ourRtn
+= sslVerifyCipher("server", serverParams
->expectCipher
,
1498 serverParams
->negCipher
);
1500 if(clientParams
->ortn
== noErr
) {
1501 ourRtn
+= sslVerifyCipher("client", clientParams
->expectCipher
,
1502 clientParams
->negCipher
);
1506 /* for workaround for Radar 4619502 */
1507 CFRelease(defaultKc
);
1513 * Add all of the roots in a given KC to SSL ctx's trusted anchors.
1515 OSStatus
sslAddTrustedRoots(
1517 SecKeychainRef keychain
,
1518 bool *foundOne
) // RETURNED, true if we found
1519 // at least one root cert
1522 SecCertificateRef secCert
;
1523 SecKeychainSearchRef srch
;
1526 ortn
= SecKeychainSearchCreateFromAttributes(keychain
,
1527 kSecCertificateItemClass
,
1531 printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn
);
1536 * Only use root certs. Not an error if we don't find any.
1539 ortn
= SecKeychainSearchCopyNext(srch
,
1540 (SecKeychainItemRef
*)&secCert
);
1545 /* see if it's a root */
1546 if(!isCertRefRoot(secCert
)) {
1550 /* Tell Secure Transport to trust this one. */
1551 ortn
= addTrustedSecCert(ctx
, secCert
, false);
1554 printSslErrStr("addTrustedSecCert", ortn
);
1559 } while(ortn
== noErr
);
1565 * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename.
1567 OSStatus
sslIdentityPicker(
1568 SecKeychainRef kcRef
, // NULL means use default list
1569 const char *trustedAnchor
, // optional additional trusted anchor
1570 bool includeRoot
, // true --> root is appended to outArray
1571 // false --> root not included
1572 const CSSM_OID
*vfyPolicy
, // optional - if NULL, use SSL
1573 CFArrayRef
*outArray
) // created and RETURNED
1575 SecCertificateRef trustedCert
= NULL
;
1579 ortn
= sslReadAnchor(trustedAnchor
, &trustedCert
);
1581 printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n",
1586 ortn
= sslIdentPicker(kcRef
, trustedCert
, includeRoot
, vfyPolicy
, outArray
);
1588 CFRelease(trustedCert
);
1594 * Given a keychain name, convert it into a full path using the "SSL regression
1595 * test suite algorithm". The Sec layer by default locates root root's keychains
1596 * in different places depending on whether we're actually logged in as root
1597 * or running via e.g. cron, so we force the location of root keychains to
1598 * a hard-coded path. User keychain names we leave alone.
1599 * This has to be kept in sync with the sslKcSetup script fragment in
1602 void sslKeychainPath(
1604 char *kcPath
) // allocd by caller, MAXPATHLEN
1606 if(kcName
[0] == '\0') {
1609 else if(geteuid() == 0) {
1611 const char *buildDir
= getenv("LOCAL_BUILD_DIR");
1612 if(buildDir
== NULL
) {
1615 sprintf(kcPath
, "%s/Library/Keychains/%s", buildDir
, kcName
);
1618 /* user, leave alone */
1619 strcpy(kcPath
, kcName
);
1623 /* Verify presence of required file. Returns nonzero if not found. */
1624 int sslCheckFile(const char *path
)
1628 if(stat(path
, &sb
)) {
1629 printf("***Can't find file %s.\n", path
);
1630 printf(" Try running in the build directory, perhaps after running the\n"
1631 " makeLocalCert script.\n");
1637 /* Stringify a SSL_ECDSA_NamedCurve */
1638 extern const char *sslCurveString(
1639 SSL_ECDSA_NamedCurve namedCurve
)
1641 static char unk
[100];
1643 switch(namedCurve
) {
1644 case SSL_Curve_None
: return "Curve_None";
1645 case SSL_Curve_secp256r1
: return "secp256r1";
1646 case SSL_Curve_secp384r1
: return "secp384r1";
1647 case SSL_Curve_secp521r1
: return "secp521r1";
1649 sprintf(unk
, "Unknown <%d>", (int)namedCurve
);