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 case SSL_NULL_WITH_NULL_NULL
:
32 return "SSL_NULL_WITH_NULL_NULL";
33 case SSL_RSA_WITH_NULL_MD5
:
34 return "SSL_RSA_WITH_NULL_MD5";
35 case SSL_RSA_WITH_NULL_SHA
:
36 return "SSL_RSA_WITH_NULL_SHA";
37 case SSL_RSA_EXPORT_WITH_RC4_40_MD5
:
38 return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
39 case SSL_RSA_WITH_RC4_128_MD5
:
40 return "SSL_RSA_WITH_RC4_128_MD5";
41 case SSL_RSA_WITH_RC4_128_SHA
:
42 return "SSL_RSA_WITH_RC4_128_SHA";
43 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
:
44 return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
45 case SSL_RSA_WITH_IDEA_CBC_SHA
:
46 return "SSL_RSA_WITH_IDEA_CBC_SHA";
47 case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
:
48 return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
49 case SSL_RSA_WITH_DES_CBC_SHA
:
50 return "SSL_RSA_WITH_DES_CBC_SHA";
51 case SSL_RSA_WITH_3DES_EDE_CBC_SHA
:
52 return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
53 case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
:
54 return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
55 case SSL_DH_DSS_WITH_DES_CBC_SHA
:
56 return "SSL_DH_DSS_WITH_DES_CBC_SHA";
57 case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
:
58 return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
59 case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
:
60 return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
61 case SSL_DH_RSA_WITH_DES_CBC_SHA
:
62 return "SSL_DH_RSA_WITH_DES_CBC_SHA";
63 case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
:
64 return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
65 case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
:
66 return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
67 case SSL_DHE_DSS_WITH_DES_CBC_SHA
:
68 return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
69 case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
:
70 return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
71 case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
:
72 return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
73 case SSL_DHE_RSA_WITH_DES_CBC_SHA
:
74 return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
75 case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
:
76 return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
77 case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
:
78 return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
79 case SSL_DH_anon_WITH_RC4_128_MD5
:
80 return "SSL_DH_anon_WITH_RC4_128_MD5";
81 case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
:
82 return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
83 case SSL_DH_anon_WITH_DES_CBC_SHA
:
84 return "SSL_DH_anon_WITH_DES_CBC_SHA";
85 case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
:
86 return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
87 case SSL_FORTEZZA_DMS_WITH_NULL_SHA
:
88 return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
89 case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA
:
90 return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
91 case SSL_RSA_WITH_RC2_CBC_MD5
:
92 return "SSL_RSA_WITH_RC2_CBC_MD5";
93 case SSL_RSA_WITH_IDEA_CBC_MD5
:
94 return "SSL_RSA_WITH_IDEA_CBC_MD5";
95 case SSL_RSA_WITH_DES_CBC_MD5
:
96 return "SSL_RSA_WITH_DES_CBC_MD5";
97 case SSL_RSA_WITH_3DES_EDE_CBC_MD5
:
98 return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
99 case SSL_NO_SUCH_CIPHERSUITE
:
100 return "SSL_NO_SUCH_CIPHERSUITE";
101 case TLS_RSA_WITH_AES_128_CBC_SHA
:
102 return "TLS_RSA_WITH_AES_128_CBC_SHA";
103 case TLS_DH_DSS_WITH_AES_128_CBC_SHA
:
104 return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
105 case TLS_DH_RSA_WITH_AES_128_CBC_SHA
:
106 return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
107 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA
:
108 return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
109 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA
:
110 return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
111 case TLS_DH_anon_WITH_AES_128_CBC_SHA
:
112 return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
113 case TLS_RSA_WITH_AES_256_CBC_SHA
:
114 return "TLS_RSA_WITH_AES_256_CBC_SHA";
115 case TLS_DH_DSS_WITH_AES_256_CBC_SHA
:
116 return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
117 case TLS_DH_RSA_WITH_AES_256_CBC_SHA
:
118 return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
119 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA
:
120 return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
121 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA
:
122 return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
123 case TLS_DH_anon_WITH_AES_256_CBC_SHA
:
124 return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
127 sprintf(noSuite
, "Unknown (%d)", (unsigned)cs
);
133 * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion -
134 * return a string representation.
136 const char *sslGetProtocolVersionString(SSLProtocol prot
)
138 static char noProt
[20];
141 case kSSLProtocolUnknown
:
142 return "kSSLProtocolUnknown";
144 return "kSSLProtocol2";
146 return "kSSLProtocol3";
147 case kSSLProtocol3Only
:
148 return "kSSLProtocol3Only";
150 return "kTLSProtocol1";
151 case kTLSProtocol1Only
:
152 return "kTLSProtocol1Only";
154 return "kTLSProtocol11";
156 return "kTLSProtocol12";
158 sprintf(noProt
, "Unknown (%d)", (unsigned)prot
);
164 * Return string representation of SecureTransport-related OSStatus.
166 const char *sslGetSSLErrString(OSStatus err
)
168 static char errSecSuccessStr
[20];
172 return "errSecSuccess";
174 return "errSecAllocate";
176 return "errSecParam";
177 case errSecUnimplemented
:
178 return "errSecUnimplemented";
182 return "errSecBadReq";
184 return "errSSLProtocol";
185 case errSSLNegotiation
:
186 return "errSSLNegotiation";
187 case errSSLFatalAlert
:
188 return "errSSLFatalAlert";
189 case errSSLWouldBlock
:
190 return "errSSLWouldBlock";
191 case errSSLSessionNotFound
:
192 return "errSSLSessionNotFound";
193 case errSSLClosedGraceful
:
194 return "errSSLClosedGraceful";
195 case errSSLClosedAbort
:
196 return "errSSLClosedAbort";
197 case errSSLXCertChainInvalid
:
198 return "errSSLXCertChainInvalid";
200 return "errSSLBadCert";
202 return "errSSLCrypto";
204 return "errSSLInternal";
205 case errSSLModuleAttach
:
206 return "errSSLModuleAttach";
207 case errSSLUnknownRootCert
:
208 return "errSSLUnknownRootCert";
209 case errSSLNoRootCert
:
210 return "errSSLNoRootCert";
211 case errSSLCertExpired
:
212 return "errSSLCertExpired";
213 case errSSLCertNotYetValid
:
214 return "errSSLCertNotYetValid";
215 case errSSLClosedNoNotify
:
216 return "errSSLClosedNoNotify";
217 case errSSLBufferOverflow
:
218 return "errSSLBufferOverflow";
219 case errSSLBadCipherSuite
:
220 return "errSSLBadCipherSuite";
221 /* TLS/Panther addenda */
222 case errSSLPeerUnexpectedMsg
:
223 return "errSSLPeerUnexpectedMsg";
224 case errSSLPeerBadRecordMac
:
225 return "errSSLPeerBadRecordMac";
226 case errSSLPeerDecryptionFail
:
227 return "errSSLPeerDecryptionFail";
228 case errSSLPeerRecordOverflow
:
229 return "errSSLPeerRecordOverflow";
230 case errSSLPeerDecompressFail
:
231 return "errSSLPeerDecompressFail";
232 case errSSLPeerHandshakeFail
:
233 return "errSSLPeerHandshakeFail";
234 case errSSLPeerBadCert
:
235 return "errSSLPeerBadCert";
236 case errSSLPeerUnsupportedCert
:
237 return "errSSLPeerUnsupportedCert";
238 case errSSLPeerCertRevoked
:
239 return "errSSLPeerCertRevoked";
240 case errSSLPeerCertExpired
:
241 return "errSSLPeerCertExpired";
242 case errSSLPeerCertUnknown
:
243 return "errSSLPeerCertUnknown";
244 case errSSLIllegalParam
:
245 return "errSSLIllegalParam";
246 case errSSLPeerUnknownCA
:
247 return "errSSLPeerUnknownCA";
248 case errSSLPeerAccessDenied
:
249 return "errSSLPeerAccessDenied";
250 case errSSLPeerDecodeError
:
251 return "errSSLPeerDecodeError";
252 case errSSLPeerDecryptError
:
253 return "errSSLPeerDecryptError";
254 case errSSLPeerExportRestriction
:
255 return "errSSLPeerExportRestriction";
256 case errSSLPeerProtocolVersion
:
257 return "errSSLPeerProtocolVersion";
258 case errSSLPeerInsufficientSecurity
:
259 return "errSSLPeerInsufficientSecurity";
260 case errSSLPeerInternalError
:
261 return "errSSLPeerInternalError";
262 case errSSLPeerUserCancelled
:
263 return "errSSLPeerUserCancelled";
264 case errSSLPeerNoRenegotiation
:
265 return "errSSLPeerNoRenegotiation";
266 case errSSLHostNameMismatch
:
267 return "errSSLHostNameMismatch";
268 case errSSLConnectionRefused
:
269 return "errSSLConnectionRefused";
270 case errSSLDecryptionFail
:
271 return "errSSLDecryptionFail";
272 case errSSLBadRecordMac
:
273 return "errSSLBadRecordMac";
274 case errSSLRecordOverflow
:
275 return "errSSLRecordOverflow";
276 case errSSLBadConfiguration
:
277 return "errSSLBadConfiguration";
279 /* some from the Sec layer */
280 case errSecNotAvailable
: return "errSecNotAvailable";
281 case errSecDuplicateItem
: return "errSecDuplicateItem";
282 case errSecItemNotFound
: return "errSecItemNotFound";
284 case errSessionInvalidId
: return "errSessionInvalidId";
285 case errSessionInvalidAttributes
: return "errSessionInvalidAttributes";
286 case errSessionAuthorizationDenied
: return "errSessionAuthorizationDenied";
287 case errSessionInternal
: return "errSessionInternal";
288 case errSessionInvalidFlags
: return "errSessionInvalidFlags";
293 if (err
< (CSSM_BASE_ERROR
+
294 (CSSM_ERRORCODE_MODULE_EXTENT
* 8)))
296 /* assume CSSM error */
297 return cssmErrToStr(err
);
302 sprintf(errSecSuccessStr
, "Unknown (%d)", (unsigned)err
);
303 return errSecSuccessStr
;
312 printf("*** %s: %s\n", op
, sslGetSSLErrString(err
));
315 const char *sslGetClientCertStateString(SSLClientCertificateState state
)
317 static char noState
[20];
320 case kSSLClientCertNone
:
321 return "ClientCertNone";
322 case kSSLClientCertRequested
:
323 return "CertRequested";
324 case kSSLClientCertSent
:
325 return "ClientCertSent";
326 case kSSLClientCertRejected
:
327 return "ClientCertRejected";
329 sprintf(noState
, "Unknown (%d)", (unsigned)state
);
336 * Convert a keychain name (which may be NULL) into the CFArrayRef required
337 * by SSLSetCertificate. This is a bare-bones example of this operation,
338 * since it requires and assumes that there is exactly one SecIdentity
339 * in the keychain - i.e., there is exactly one matching cert/private key
340 * pair. A real world server would probably search a keychain for a SecIdentity
341 * matching some specific criteria.
343 CFArrayRef
getSslCerts(
344 const char *kcName
, // may be NULL, i.e., use default
346 bool completeCertChain
,
347 const char *anchorFile
, // optional trusted anchor
348 SecKeychainRef
*pKcRef
) // RETURNED
351 SecKeychainRef kcRef
= nil
;
356 /* pick a keychain */
358 ortn
= SecKeychainOpen(kcName
, &kcRef
);
360 printf("SecKeychainOpen returned %d.\n", (int)ortn
);
361 printf("Cannot open keychain at %s. Aborting.\n", kcName
);
366 /* use default keychain */
367 ortn
= SecKeychainCopyDefault(&kcRef
);
369 printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn
);
374 return sslKcRefToCertArray(kcRef
, encryptOnly
, completeCertChain
, anchorFile
);
376 SecCertificateRef cert
= NULL
;
377 SecIdentityRef identity
= NULL
;
378 CFMutableArrayRef certificates
= NULL
, result
= NULL
;
379 CFMutableDictionaryRef certQuery
= NULL
, keyQuery
= NULL
, keyResult
= NULL
;
380 SecTrustRef trust
= NULL
;
381 SecKeyRef key
= NULL
;
382 CFTypeRef pkdigest
= NULL
;
384 // Find the first private key in the keychain and return both it's
385 // attributes and a ref to it.
386 require(keyQuery
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
), errOut
);
387 CFDictionaryAddValue(keyQuery
, kSecClass
, kSecClassKey
);
388 CFDictionaryAddValue(keyQuery
, kSecAttrKeyClass
, kSecAttrKeyClassPrivate
);
389 CFDictionaryAddValue(keyQuery
, kSecReturnRef
, kCFBooleanTrue
);
390 CFDictionaryAddValue(keyQuery
, kSecReturnAttributes
, kCFBooleanTrue
);
391 require_noerr(SecItemCopyMatching(keyQuery
, (CFTypeRef
*)&keyResult
),
393 require(key
= (SecKeyRef
)CFDictionaryGetValue(keyResult
, kSecValueRef
),
395 require(pkdigest
= CFDictionaryGetValue(keyResult
, kSecAttrApplicationLabel
),
398 // Find the first certificate that has the same public key hash as the
399 // returned private key and return it as a ref.
400 require(certQuery
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
), errOut
);
401 CFDictionaryAddValue(certQuery
, kSecClass
, kSecClassCertificate
);
402 CFDictionaryAddValue(certQuery
, kSecAttrPublicKeyHash
, pkdigest
);
403 CFDictionaryAddValue(certQuery
, kSecReturnRef
, kCFBooleanTrue
);
404 require_noerr(SecItemCopyMatching(certQuery
, (CFTypeRef
*)&cert
), errOut
);
406 // Create an identity from the key and certificate.
407 require(identity
= SecIdentityCreate(NULL
, cert
, key
), errOut
);
409 // Build a (partial) certificate chain from cert
410 require(certificates
= CFArrayCreateMutable(NULL
, 0,
411 &kCFTypeArrayCallBacks
), errOut
);
412 CFArrayAppendValue(certificates
, cert
);
413 require_noerr(SecTrustCreateWithCertificates(certificates
, NULL
, &trust
),
415 SecTrustResultType tresult
;
416 require_noerr(SecTrustEvaluate(trust
, &tresult
), errOut
);
418 CFIndex certCount
, ix
;
419 // We need at least 1 certificate
420 require(certCount
= SecTrustGetCertificateCount(trust
), errOut
);
422 // Build a result where element 0 is the identity and the other elements
423 // are the certs in the chain starting at the first intermediate up to the
424 // anchor, if we found one, or as far as we were able to build the chain
426 require(result
= CFArrayCreateMutable(NULL
, certCount
, &kCFTypeArrayCallBacks
),
429 // We are commited to returning a result now, so do not use require below
430 // this line without setting result to NULL again.
431 CFArrayAppendValue(result
, identity
);
432 for (ix
= 1; ix
< certCount
; ++ix
) {
433 CFArrayAppendValue(result
, SecTrustGetCertificateAtIndex(trust
, ix
));
437 CFReleaseSafe(trust
);
438 CFReleaseSafe(certificates
);
439 CFReleaseSafe(identity
);
441 CFReleaseSafe(certQuery
);
442 CFReleaseSafe(keyResult
);
443 CFReleaseSafe(keyQuery
);
451 * Determine if specified SecCertificateRef is a self-signed cert.
452 * We do this by comparing the subject and issuerr names; no cryptographic
453 * verification is performed.
455 * Returns true if the cert appears to be a root.
457 static bool isCertRefRoot(
458 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
;
472 OSStatus ortn
= SecKeychainItemCopyAttributesAndData(
473 (SecKeychainItemRef
)certRef
,
477 NULL
, // length - don't need the data
480 cssmPerror("SecKeychainItemCopyAttributesAndData", ortn
);
481 /* may want to be a bit more robust here, but this should
485 /* subsequent errors to errOut: */
487 if((attrList
== NULL
) || (attrList
->count
!= 2)) {
488 printf("***Unexpected result fetching label attr\n");
492 /* rootness is just byte-for-byte compare of the two names */
493 attr1
= &attrList
->attr
[0];
494 attr2
= &attrList
->attr
[1];
495 if(attr1
->length
== attr2
->length
) {
496 if(memcmp(attr1
->data
, attr2
->data
, attr1
->length
) == 0) {
501 SecKeychainItemFreeAttributesAndData(attrList
, NULL
);
509 * Given a SecIdentityRef, do our best to construct a complete, ordered, and
510 * verified cert chain, returning the result in a CFArrayRef. The result is
511 * suitable for use when calling SSLSetCertificate().
513 OSStatus
sslCompleteCertChain(
514 SecIdentityRef identity
,
515 SecCertificateRef trustedAnchor
, // optional additional trusted anchor
516 bool includeRoot
, // include the root in outArray
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
;
546 return errSecSuccess
;
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 generic X509 cert chain verification */
562 ortn
= SecPolicySearchCreate(CSSM_CERT_X_509v3
,
563 &CSSMOID_APPLE_X509_BASIC
,
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");
628 ortn
= errSecSuccess
;
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",
653 ortn
= errSecSuccess
;
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
,
690 bool completeCertChain
,
691 const char *trustedAnchorFile
)
693 /* quick check to make sure the keychain exists */
694 SecKeychainStatus kcStat
;
695 OSStatus ortn
= SecKeychainGetStatus(kcRef
, &kcStat
);
697 printSslErrStr("SecKeychainGetStatus", ortn
);
698 printf("Can not open keychain. Aborting.\n");
703 * Search for "any" identity matching specified key use;
704 * in this app, we expect there to be exactly one.
706 SecIdentitySearchRef srchRef
= nil
;
707 ortn
= SecIdentitySearchCreate(kcRef
,
708 encryptOnly
? CSSM_KEYUSE_DECRYPT
: CSSM_KEYUSE_SIGN
,
711 printf("SecIdentitySearchCreate returned %d.\n", (int)ortn
);
712 printf("Cannot find signing key in keychain. Aborting.\n");
715 SecIdentityRef identity
= nil
;
716 ortn
= SecIdentitySearchCopyNext(srchRef
, &identity
);
718 printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn
);
719 printf("Cannot find signing key in keychain. Aborting.\n");
722 if(CFGetTypeID(identity
) != SecIdentityGetTypeID()) {
723 printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
730 if(completeCertChain
) {
732 * Place it and the other certs needed to verify it -
733 * up to but not including the root - in a CFArray.
735 SecCertificateRef anchorCert
= NULL
;
736 if(trustedAnchorFile
) {
737 ortn
= sslReadAnchor(trustedAnchorFile
, &anchorCert
);
739 printf("***Error reading anchor file\n");
743 ortn
= sslCompleteCertChain(identity
, anchorCert
, false, &ca
);
745 CFRelease(anchorCert
);
750 /* simple case, just this one identity */
751 CFArrayRef ca
= CFArrayCreate(NULL
,
752 (const void **)&identity
,
756 printf("CFArrayCreate error\n");
763 OSStatus
addTrustedSecCert(
765 SecCertificateRef secCert
,
769 CFMutableArrayRef array
;
771 if(secCert
== NULL
) {
772 printf("***addTrustedSecCert screwup\n");
775 array
= CFArrayCreateMutable(kCFAllocatorDefault
,
776 (CFIndex
)1, &kCFTypeArrayCallBacks
);
778 return errSecAllocate
;
780 CFArrayAppendValue(array
, secCert
);
781 ortn
= SSLSetTrustedRoots(ctx
, array
, replaceAnchors
? true : false);
783 printSslErrStr("SSLSetTrustedRoots", ortn
);
790 OSStatus
sslReadAnchor(
791 const char *anchorFile
,
792 SecCertificateRef
*certRef
)
795 SecCertificateRef secCert
;
796 unsigned char *certData
;
800 if(readFile(anchorFile
, &certData
, &certLen
)) {
803 cert
.Data
= certData
;
804 cert
.Length
= certLen
;
805 ortn
= SecCertificateCreateFromData(&cert
,
807 CSSM_CERT_ENCODING_DER
,
811 printf("***SecCertificateCreateFromData returned %d\n", (int)ortn
);
815 return errSecSuccess
;
819 OSStatus
sslAddTrustedRoot(
821 const char *anchorFile
,
826 SecCertificateRef secCert
;
828 ortn
= sslReadAnchor(anchorFile
, &secCert
);
830 printf("***Error reading %s. SSLSetTrustedRoots skipped.\n",
834 return addTrustedSecCert(ctx
, secCert
, replaceAnchors
);
841 /* Per 3537606 this is no longer necessary */
843 * Assume incoming identity contains a root (e.g., created by
844 * certtool) and add that cert to ST's trusted anchors. This
845 * enables ST's verify of the incoming chain to succeed without
846 * a kludgy "AllowAnyRoot" specification.
848 OSStatus
addIdentityAsTrustedRoot(
850 CFArrayRef identArray
)
852 CFIndex numItems
= CFArrayGetCount(identArray
);
854 printf("***addIdentityAsTrustedRoot: empty identArray\n");
858 /* Root should be the last item - could be identity, could be cert */
859 CFTypeRef theItem
= CFArrayGetValueAtIndex(identArray
, numItems
- 1);
860 if(CFGetTypeID(theItem
) == SecIdentityGetTypeID()) {
862 SecCertificateRef certRef
;
863 OSStatus ortn
= SecIdentityCopyCertificate(
864 (SecIdentityRef
)theItem
, &certRef
);
866 cssmPerror("SecIdentityCopyCertificate", ortn
);
867 printf("***Error gettting cert from identity\n");
870 ortn
= addTrustedSecCert(ctx
, certRef
, false);
874 else if(CFGetTypeID(theItem
) == SecCertificateGetTypeID()) {
876 return addTrustedSecCert(ctx
, (SecCertificateRef
)theItem
, false);
879 printf("***Bogus item in identity array\n");
884 OSStatus
addIdentityAsTrustedRoot(
886 CFArrayRef identArray
)
888 return errSecSuccess
;
893 * Lists of SSLCipherSuites used in sslSetCipherRestrictions. Note that the
894 * SecureTransport library does not implement all of these; we only specify
895 * the ones it claims to support.
897 const SSLCipherSuite suites40
[] = {
898 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
899 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
900 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
901 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
902 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
903 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
904 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
905 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
906 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
907 SSL_NO_SUCH_CIPHERSUITE
909 const SSLCipherSuite suitesDES
[] = {
910 SSL_RSA_WITH_DES_CBC_SHA
,
911 SSL_DH_DSS_WITH_DES_CBC_SHA
,
912 SSL_DH_RSA_WITH_DES_CBC_SHA
,
913 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
914 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
915 SSL_DH_anon_WITH_DES_CBC_SHA
,
916 SSL_RSA_WITH_DES_CBC_MD5
,
917 SSL_NO_SUCH_CIPHERSUITE
919 const SSLCipherSuite suitesDES40
[] = {
920 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
921 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
922 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
923 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
924 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
925 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
926 SSL_NO_SUCH_CIPHERSUITE
928 const SSLCipherSuite suites3DES
[] = {
929 SSL_RSA_WITH_3DES_EDE_CBC_SHA
,
930 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
931 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
932 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
933 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
934 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
935 SSL_RSA_WITH_3DES_EDE_CBC_MD5
,
936 SSL_NO_SUCH_CIPHERSUITE
938 const SSLCipherSuite suitesRC4
[] = {
939 SSL_RSA_WITH_RC4_128_MD5
,
940 SSL_RSA_WITH_RC4_128_SHA
,
941 SSL_DH_anon_WITH_RC4_128_MD5
,
942 SSL_NO_SUCH_CIPHERSUITE
944 const SSLCipherSuite suitesRC4_40
[] = {
945 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
946 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
947 SSL_NO_SUCH_CIPHERSUITE
949 const SSLCipherSuite suitesRC2
[] = {
950 SSL_RSA_WITH_RC2_CBC_MD5
,
951 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
952 SSL_NO_SUCH_CIPHERSUITE
954 const SSLCipherSuite suitesAES128
[] = {
955 TLS_RSA_WITH_AES_128_CBC_SHA
,
956 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
957 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
958 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
959 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
960 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
961 SSL_NO_SUCH_CIPHERSUITE
963 const SSLCipherSuite suitesAES256
[] = {
964 TLS_RSA_WITH_AES_256_CBC_SHA
,
965 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
966 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
967 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
968 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
969 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
970 SSL_NO_SUCH_CIPHERSUITE
972 const SSLCipherSuite suitesDH
[] = {
973 SSL_DH_DSS_WITH_DES_CBC_SHA
,
974 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
975 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
976 SSL_DH_RSA_WITH_DES_CBC_SHA
,
977 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
978 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
979 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
980 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
981 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
982 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
983 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
984 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
985 SSL_DH_anon_WITH_RC4_128_MD5
,
986 SSL_DH_anon_WITH_DES_CBC_SHA
,
987 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
988 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
989 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
990 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
991 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
992 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
993 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
994 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
995 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
996 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
997 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
998 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
999 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
1000 SSL_NO_SUCH_CIPHERSUITE
1002 const SSLCipherSuite suitesDHAnon
[] = {
1003 SSL_DH_anon_WITH_RC4_128_MD5
,
1004 SSL_DH_anon_WITH_DES_CBC_SHA
,
1005 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
1006 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
1007 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
1008 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
1009 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
1010 SSL_NO_SUCH_CIPHERSUITE
1012 const SSLCipherSuite suitesDH_RSA
[] = {
1013 SSL_DH_RSA_WITH_DES_CBC_SHA
,
1014 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
1015 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
1016 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
1017 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1018 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1019 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
1020 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
1021 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
1022 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
1023 SSL_NO_SUCH_CIPHERSUITE
1025 const SSLCipherSuite suitesDH_DSS
[] = {
1026 SSL_DH_DSS_WITH_DES_CBC_SHA
,
1027 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
1028 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
1029 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
1030 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1031 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1032 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
1033 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
1034 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
1035 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
1036 SSL_NO_SUCH_CIPHERSUITE
1038 const SSLCipherSuite suites_SHA1
[] = {
1039 SSL_RSA_WITH_RC4_128_SHA
,
1040 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1041 SSL_RSA_WITH_IDEA_CBC_SHA
,
1042 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1043 SSL_RSA_WITH_DES_CBC_SHA
,
1044 SSL_RSA_WITH_3DES_EDE_CBC_SHA
,
1045 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1046 SSL_DH_DSS_WITH_DES_CBC_SHA
,
1047 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
1048 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1049 SSL_DH_RSA_WITH_DES_CBC_SHA
,
1050 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
1051 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1052 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
1053 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
1054 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1055 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
1056 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
1057 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
1058 SSL_DH_anon_WITH_DES_CBC_SHA
,
1059 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
1060 SSL_FORTEZZA_DMS_WITH_NULL_SHA
,
1061 SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA
,
1062 TLS_RSA_WITH_AES_128_CBC_SHA
,
1063 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
1064 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
1065 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
1066 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
1067 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
1068 TLS_RSA_WITH_AES_256_CBC_SHA
,
1069 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
1070 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
1071 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
1072 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
1073 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
1074 SSL_NO_SUCH_CIPHERSUITE
1076 const SSLCipherSuite suites_MD5
[] = {
1077 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
1078 SSL_RSA_WITH_RC4_128_MD5
,
1079 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
1080 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
1081 SSL_DH_anon_WITH_RC4_128_MD5
,
1082 SSL_NO_SUCH_CIPHERSUITE
1087 * Given an SSLContextRef and an array of SSLCipherSuites, terminated by
1088 * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library
1089 * supports and do a SSLSetEnabledCiphers() specifying those.
1091 OSStatus
sslSetEnabledCiphers(
1093 const SSLCipherSuite
*ciphers
)
1095 size_t numSupported
;
1097 SSLCipherSuite
*supported
= NULL
;
1098 SSLCipherSuite
*enabled
= NULL
;
1099 unsigned enabledDex
= 0; // index into enabled
1100 unsigned supportedDex
= 0; // index into supported
1101 unsigned inDex
= 0; // index into ciphers
1103 /* first get all the supported ciphers */
1104 ortn
= SSLGetNumberSupportedCiphers(ctx
, &numSupported
);
1106 printSslErrStr("SSLGetNumberSupportedCiphers", ortn
);
1109 supported
= (SSLCipherSuite
*)malloc(numSupported
* sizeof(SSLCipherSuite
));
1110 ortn
= SSLGetSupportedCiphers(ctx
, supported
, &numSupported
);
1112 printSslErrStr("SSLGetSupportedCiphers", ortn
);
1117 * Malloc an array we'll use for SSLGetEnabledCiphers - this will be
1118 * bigger than the number of suites we actually specify
1120 enabled
= (SSLCipherSuite
*)malloc(numSupported
* sizeof(SSLCipherSuite
));
1123 * For each valid suite in ciphers, see if it's in the list of
1124 * supported ciphers. If it is, add it to the list of ciphers to be
1127 for(inDex
=0; ciphers
[inDex
] != SSL_NO_SUCH_CIPHERSUITE
; inDex
++) {
1128 for(supportedDex
=0; supportedDex
<numSupported
; supportedDex
++) {
1129 if(ciphers
[inDex
] == supported
[supportedDex
]) {
1130 enabled
[enabledDex
++] = ciphers
[inDex
];
1136 /* send it on down. */
1137 ortn
= SSLSetEnabledCiphers(ctx
, enabled
, enabledDex
);
1139 printSslErrStr("SSLSetEnabledCiphers", ortn
);
1147 * Specify a restricted set of cipherspecs.
1149 OSStatus
sslSetCipherRestrictions(
1151 char cipherRestrict
)
1155 if(cipherRestrict
== '\0') {
1156 return errSecSuccess
; // actually should not have been called
1158 switch(cipherRestrict
) {
1160 ortn
= sslSetEnabledCiphers(ctx
, suites40
);
1163 ortn
= sslSetEnabledCiphers(ctx
, suitesDES
);
1166 ortn
= sslSetEnabledCiphers(ctx
, suitesDES40
);
1169 ortn
= sslSetEnabledCiphers(ctx
, suites3DES
);
1172 ortn
= sslSetEnabledCiphers(ctx
, suitesRC4
);
1175 ortn
= sslSetEnabledCiphers(ctx
, suitesRC4_40
);
1178 ortn
= sslSetEnabledCiphers(ctx
, suitesRC2
);
1181 ortn
= sslSetEnabledCiphers(ctx
, suitesAES128
);
1184 ortn
= sslSetEnabledCiphers(ctx
, suitesAES256
);
1187 ortn
= sslSetEnabledCiphers(ctx
, suitesDH
);
1190 ortn
= sslSetEnabledCiphers(ctx
, suitesDHAnon
);
1193 ortn
= sslSetEnabledCiphers(ctx
, suitesDH_RSA
);
1196 ortn
= sslSetEnabledCiphers(ctx
, suitesDH_DSS
);
1199 printf("***bad cipherSpec***\n");
1206 int sslVerifyClientCertState(
1207 char *whichSide
, // "client" or "server"
1208 SSLClientCertificateState expectState
,
1209 SSLClientCertificateState gotState
)
1211 if(expectState
== SSL_CLIENT_CERT_IGNORE
) {
1212 /* app says "don't bopther checking" */
1215 if(expectState
== gotState
) {
1218 printf("***%s: Expected clientCertState %s; got %s\n", whichSide
,
1219 sslGetClientCertStateString(expectState
),
1220 sslGetClientCertStateString(gotState
));
1225 char *whichSide
, // "client" or "server"
1229 if(expectRtn
== gotRtn
) {
1232 printf("***%s: Expected return %s; got %s\n", whichSide
,
1233 sslGetSSLErrString(expectRtn
),
1234 sslGetSSLErrString(gotRtn
));
1238 int sslVerifyProtVers(
1239 char *whichSide
, // "client" or "server"
1240 SSLProtocol expectProt
,
1241 SSLProtocol gotProt
)
1243 if(expectProt
== SSL_PROTOCOL_IGNORE
) {
1244 /* app says "don't bopther checking" */
1247 if(expectProt
== gotProt
) {
1250 printf("***%s: Expected return %s; got %s\n", whichSide
,
1251 sslGetProtocolVersionString(expectProt
),
1252 sslGetProtocolVersionString(gotProt
));
1256 int sslVerifyCipher(
1257 char *whichSide
, // "client" or "server"
1258 SSLCipherSuite expectCipher
,
1259 SSLCipherSuite gotCipher
)
1261 if(expectCipher
== SSL_CIPHER_IGNORE
) {
1262 /* app says "don't bopther checking" */
1265 if(expectCipher
== gotCipher
) {
1268 printf("***%s: Expected return %s; got %s\n", whichSide
,
1269 sslGetCipherSuiteString(expectCipher
),
1270 sslGetCipherSuiteString(gotCipher
));
1275 OSStatus
sslSetProtocols(
1277 const char *acceptedProts
,
1278 SSLProtocol tryVersion
) // only used if acceptedProts NULL
1284 printf("***SSLSetProtocolVersionEnabled not supported in this config.\n");
1287 ortn
= SSLSetProtocolVersionEnabled(ctx
, kSSLProtocolAll
, false);
1289 printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn
);
1292 for(const char *cp
= acceptedProts
; *cp
; cp
++) {
1296 prot
= kSSLProtocol2
;
1299 prot
= kSSLProtocol3
;
1302 prot
= kTLSProtocol1
;
1305 printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts
);
1308 ortn
= SSLSetProtocolVersionEnabled(ctx
, prot
, true);
1310 printSslErrStr("SSLSetProtocolVersionEnabled", ortn
);
1316 ortn
= SSLSetProtocolVersion(ctx
, tryVersion
);
1318 printSslErrStr("SSLSetProtocolVersion", ortn
);
1322 return errSecSuccess
;
1326 char *whichSide
, // "client" or "server"
1327 SslAppTestParams
*params
)
1329 printf("%s status:\n", whichSide
);
1330 if(params
->acceptedProts
) {
1331 printf(" Allowed SSL versions : %s\n", params
->acceptedProts
);
1334 printf(" Attempted SSL version : %s\n",
1335 sslGetProtocolVersionString(params
->tryVersion
));
1337 printf(" Result : %s\n", sslGetSSLErrString(params
->ortn
));
1338 printf(" Negotiated SSL version : %s\n",
1339 sslGetProtocolVersionString(params
->negVersion
));
1340 printf(" Negotiated CipherSuite : %s\n",
1341 sslGetCipherSuiteString(params
->negCipher
));
1342 if(params
->certState
!= kSSLClientCertNone
) {
1343 printf(" Client Cert State : %s\n",
1344 sslGetClientCertStateString(params
->certState
));
1349 /* print a '.' every few seconds to keep UI alive while connecting */
1350 static time_t lastTime
= (time_t)0;
1351 #define TIME_INTERVAL 3
1355 time_t thisTime
= time(0);
1357 if((thisTime
- lastTime
) >= TIME_INTERVAL
) {
1358 printf("."); fflush(stdout
);
1359 lastTime
= thisTime
;
1364 /* main server pthread body */
1365 static void *sslServerThread(void *arg
)
1367 SslAppTestParams
*testParams
= (SslAppTestParams
*)arg
;
1370 status
= sslAppServe(testParams
);
1371 pthread_exit((void*)status
);
1373 return (void *)status
;
1377 * Run one session, with the server in a separate thread.
1378 * On entry, serverParams->port is the port we attempt to run on;
1379 * the server thread may overwrite that with a different port if it's
1380 * unable to open the port we specify. Whatever is left in
1381 * serverParams->port is what's used for the client side.
1383 #define CLIENT_WAIT_SECONDS 1
1385 SslAppTestParams
*serverParams
,
1386 SslAppTestParams
*clientParams
,
1387 const char *testDesc
)
1389 pthread_t serverPthread
;
1393 if(testDesc
&& !clientParams
->quiet
) {
1394 printf("===== %s =====\n", testDesc
);
1397 if(pthread_mutex_init(&serverParams
->pthreadMutex
, NULL
)) {
1398 printf("***Error initializing mutex; aborting.\n");
1401 if(pthread_cond_init(&serverParams
->pthreadCond
, NULL
)) {
1402 printf("***Error initializing pthreadCond; aborting.\n");
1405 serverParams
->serverReady
= false; // server sets true
1407 int result
= pthread_create(&serverPthread
, NULL
,
1408 sslServerThread
, serverParams
);
1410 printf("***Error starting up server thread; aborting.\n");
1414 /* wait for server to set up a socket we can connect to */
1415 if(pthread_mutex_lock(&serverParams
->pthreadMutex
)) {
1416 printf("***Error acquiring server lock; aborting.\n");
1419 while(!serverParams
->serverReady
) {
1420 if(pthread_cond_wait(&serverParams
->pthreadCond
, &serverParams
->pthreadMutex
)) {
1421 printf("***Error waiting server thread; aborting.\n");
1425 pthread_mutex_unlock(&serverParams
->pthreadMutex
);
1426 pthread_cond_destroy(&serverParams
->pthreadCond
);
1427 pthread_mutex_destroy(&serverParams
->pthreadMutex
);
1429 clientParams
->port
= serverParams
->port
;
1430 clientRtn
= sslAppClient(clientParams
);
1431 /* server doesn't shut down its socket until it sees this */
1432 serverParams
->clientDone
= 1;
1433 result
= pthread_join(serverPthread
, &serverRtn
);
1435 printf("***pthread_join returned %d, aborting\n", result
);
1439 if(serverParams
->verbose
) {
1440 sslShowResult("server", serverParams
);
1442 if(clientParams
->verbose
) {
1443 sslShowResult("client", clientParams
);
1446 /* verify results */
1448 ourRtn
+= sslVerifyRtn("server", serverParams
->expectRtn
, serverParams
->ortn
);
1449 ourRtn
+= sslVerifyRtn("client", clientParams
->expectRtn
, clientParams
->ortn
);
1450 ourRtn
+= sslVerifyProtVers("server", serverParams
->expectVersion
,
1451 serverParams
->negVersion
);
1452 ourRtn
+= sslVerifyProtVers("client", clientParams
->expectVersion
,
1453 clientParams
->negVersion
);
1454 ourRtn
+= sslVerifyClientCertState("server", serverParams
->expectCertState
,
1455 serverParams
->certState
);
1456 ourRtn
+= sslVerifyClientCertState("client", clientParams
->expectCertState
,
1457 clientParams
->certState
);
1458 if(serverParams
->ortn
== errSecSuccess
) {
1459 ourRtn
+= sslVerifyCipher("server", serverParams
->expectCipher
,
1460 serverParams
->negCipher
);
1462 if(clientParams
->ortn
== errSecSuccess
) {
1463 ourRtn
+= sslVerifyCipher("client", clientParams
->expectCipher
,
1464 clientParams
->negCipher
);
1469 static bool isCertRoot(
1470 SecCertificateRef cert
)
1472 /* FIXME - per Radar 3247491, the Sec-level functions we'd like to use for this
1473 * haven't been written yet...
1474 CSSM_X509_NAME subject;
1475 CSSM_X509_NAME issuer;
1482 * Add all of the roots in a given KC to SSL ctx's trusted anchors.
1484 OSStatus
sslAddTrustedRoots(
1486 SecKeychainRef keychain
,
1487 bool *foundOne
) // RETURNED, true if we found
1488 // at least one root cert
1491 SecCertificateRef secCert
;
1492 SecKeychainSearchRef srch
;
1495 ortn
= SecKeychainSearchCreateFromAttributes(keychain
,
1496 kSecCertificateItemClass
,
1500 printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn
);
1505 * Only use root certs. Not an error if we don't find any.
1508 ortn
= SecKeychainSearchCopyNext(srch
,
1509 (SecKeychainItemRef
*)&secCert
);
1514 /* see if it's a root */
1515 if(!isCertRoot(secCert
)) {
1519 /* Tell Secure Transport to trust this one. */
1520 ortn
= addTrustedSecCert(ctx
, secCert
, false);
1523 printSslErrStr("addTrustedSecCert", ortn
);
1528 } while(ortn
== errSecSuccess
);
1530 return errSecSuccess
;
1534 * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename.
1536 OSStatus
sslIdentityPicker(
1537 SecKeychainRef kcRef
, // NULL means use default list
1538 const char *trustedAnchor
, // optional additional trusted anchor
1539 bool includeRoot
, // true --> root is appended to outArray
1540 // false --> root not included
1541 CFArrayRef
*outArray
) // created and RETURNED
1543 SecCertificateRef trustedCert
= NULL
;
1547 ortn
= sslReadAnchor(trustedAnchor
, &trustedCert
);
1549 printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n",
1554 ortn
= sslIdentPicker(kcRef
, trustedCert
, includeRoot
, outArray
);
1556 CFRelease(trustedCert
);
1562 * Given a keychain name, convert it into a full path using the "SSL regression
1563 * test suite algorithm". The Sec layer by default locates root root's keychains
1564 * in different places depending on whether we're actually logged in as root
1565 * or running via e.g. cron, so we force the location of root keychains to
1566 * a hard-coded path. User keychain names we leave alone.
1568 void sslKeychainPath(
1570 char *kcPath
) // allocd by caller, MAXPATHLEN
1572 if(kcName
[0] == '\0') {
1575 else if(geteuid() == 0) {
1577 sprintf(kcPath
, "/Library/Keychains/%s", kcName
);
1580 /* user, leave alone */
1581 strcpy(kcPath
, kcName
);
1585 /* Verify presence of required file. Returns nonzero if not found. */
1586 int sslCheckFile(const char *path
)
1590 if(stat(path
, &sb
)) {
1591 printf("***Can't find file %s.\n", path
);
1592 printf(" Try running in the build directory, perhaps after running the\n"
1593 " makeLocalCert script.\n");
1601 /* Stringify a SSL_ECDSA_NamedCurve */
1602 extern const char *sslCurveString(
1603 SSL_ECDSA_NamedCurve namedCurve
)
1605 static char unk
[100];
1607 switch(namedCurve
) {
1608 case SSL_Curve_None
: return "Curve_None";
1609 case SSL_Curve_secp256r1
: return "secp256r1";
1610 case SSL_Curve_secp384r1
: return "secp384r1";
1611 case SSL_Curve_secp521r1
: return "secp521r1";
1613 sprintf(unk
, "Unknown <%d>", (int)namedCurve
);