]> git.saurik.com Git - apple/security.git/blob - sslViewer/sslAppUtils.cpp
Security-57031.30.12.tar.gz
[apple/security.git] / sslViewer / sslAppUtils.cpp
1 /*
2 * Copyright (c) 2006-2008,2010-2013 Apple Inc. All Rights Reserved.
3 */
4
5 #include "sslAppUtils.h"
6 //#include "sslThreading.h"
7 //#include "identPicker.h"
8 //#include <utilLib/common.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <sys/param.h>
12 #include <Security/SecBase.h>
13
14 #include <CoreFoundation/CoreFoundation.h>
15 #include <Security/Security.h>
16 #include <Security/SecIdentityPriv.h>
17 #include <AssertMacros.h>
18 #include <sys/time.h>
19
20 #include "utilities/SecCFRelease.h"
21
22 /* Set true when PR-3074739 is merged to TOT */
23 #define NEW_SSL_ERRS_3074739 1
24
25
26 const char *sslGetCipherSuiteString(SSLCipherSuite cs)
27 {
28 static char noSuite[40];
29
30 switch(cs) {
31 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";
125
126 default:
127 sprintf(noSuite, "Unknown (%d)", (unsigned)cs);
128 return noSuite;
129 }
130 }
131
132 /*
133 * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion -
134 * return a string representation.
135 */
136 const char *sslGetProtocolVersionString(SSLProtocol prot)
137 {
138 static char noProt[20];
139
140 switch(prot) {
141 case kSSLProtocolUnknown:
142 return "kSSLProtocolUnknown";
143 case kSSLProtocol2:
144 return "kSSLProtocol2";
145 case kSSLProtocol3:
146 return "kSSLProtocol3";
147 case kSSLProtocol3Only:
148 return "kSSLProtocol3Only";
149 case kTLSProtocol1:
150 return "kTLSProtocol1";
151 case kTLSProtocol1Only:
152 return "kTLSProtocol1Only";
153 case kTLSProtocol11:
154 return "kTLSProtocol11";
155 case kTLSProtocol12:
156 return "kTLSProtocol12";
157 default:
158 sprintf(noProt, "Unknown (%d)", (unsigned)prot);
159 return noProt;
160 }
161 }
162
163 /*
164 * Return string representation of SecureTransport-related OSStatus.
165 */
166 const char *sslGetSSLErrString(OSStatus err)
167 {
168 static char errSecSuccessStr[20];
169
170 switch(err) {
171 case errSecSuccess:
172 return "errSecSuccess";
173 case errSecAllocate:
174 return "errSecAllocate";
175 case errSecParam:
176 return "errSecParam";
177 case errSecUnimplemented:
178 return "errSecUnimplemented";
179 case errSecIO:
180 return "errSecIO";
181 case errSecBadReq:
182 return "errSecBadReq";
183 case errSSLProtocol:
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";
199 case errSSLBadCert:
200 return "errSSLBadCert";
201 case errSSLCrypto:
202 return "errSSLCrypto";
203 case errSSLInternal:
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";
278
279 /* some from the Sec layer */
280 case errSecNotAvailable: return "errSecNotAvailable";
281 case errSecDuplicateItem: return "errSecDuplicateItem";
282 case errSecItemNotFound: return "errSecItemNotFound";
283 #if 0
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";
289 #endif
290
291 default:
292 #if 0
293 if (err < (CSSM_BASE_ERROR +
294 (CSSM_ERRORCODE_MODULE_EXTENT * 8)))
295 {
296 /* assume CSSM error */
297 return cssmErrToStr(err);
298 }
299 else
300 #endif
301 {
302 sprintf(errSecSuccessStr, "Unknown (%d)", (unsigned)err);
303 return errSecSuccessStr;
304 }
305 }
306 }
307
308 void printSslErrStr(
309 const char *op,
310 OSStatus err)
311 {
312 printf("*** %s: %s\n", op, sslGetSSLErrString(err));
313 }
314
315 const char *sslGetClientCertStateString(SSLClientCertificateState state)
316 {
317 static char noState[20];
318
319 switch(state) {
320 case kSSLClientCertNone:
321 return "ClientCertNone";
322 case kSSLClientCertRequested:
323 return "CertRequested";
324 case kSSLClientCertSent:
325 return "ClientCertSent";
326 case kSSLClientCertRejected:
327 return "ClientCertRejected";
328 default:
329 sprintf(noState, "Unknown (%d)", (unsigned)state);
330 return noState;
331 }
332
333 }
334
335 /*
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.
342 */
343 CFArrayRef getSslCerts(
344 const char *kcName, // may be NULL, i.e., use default
345 bool encryptOnly,
346 bool completeCertChain,
347 const char *anchorFile, // optional trusted anchor
348 SecKeychainRef *pKcRef) // RETURNED
349 {
350 #if 0
351 SecKeychainRef kcRef = nil;
352 OSStatus ortn;
353
354 *pKcRef = nil;
355
356 /* pick a keychain */
357 if(kcName) {
358 ortn = SecKeychainOpen(kcName, &kcRef);
359 if(ortn) {
360 printf("SecKeychainOpen returned %d.\n", (int)ortn);
361 printf("Cannot open keychain at %s. Aborting.\n", kcName);
362 return NULL;
363 }
364 }
365 else {
366 /* use default keychain */
367 ortn = SecKeychainCopyDefault(&kcRef);
368 if(ortn) {
369 printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn);
370 return nil;
371 }
372 }
373 *pKcRef = kcRef;
374 return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile);
375 #else
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;
383
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),
392 errOut);
393 require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef),
394 errOut);
395 require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel),
396 errOut);
397
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);
405
406 // Create an identity from the key and certificate.
407 require(identity = SecIdentityCreate(NULL, cert, key), errOut);
408
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),
414 errOut);
415 SecTrustResultType tresult;
416 require_noerr(SecTrustEvaluate(trust, &tresult), errOut);
417
418 CFIndex certCount, ix;
419 // We need at least 1 certificate
420 require(certCount = SecTrustGetCertificateCount(trust), errOut);
421
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
425 // if not.
426 require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks),
427 errOut);
428
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));
434 }
435
436 errOut:
437 CFReleaseSafe(trust);
438 CFReleaseSafe(certificates);
439 CFReleaseSafe(identity);
440 CFReleaseSafe(cert);
441 CFReleaseSafe(certQuery);
442 CFReleaseSafe(keyResult);
443 CFReleaseSafe(keyQuery);
444
445 return result;
446 #endif
447 }
448
449 #if 0
450 /*
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.
454 *
455 * Returns true if the cert appears to be a root.
456 */
457 static bool isCertRefRoot(
458 SecCertificateRef certRef)
459 {
460 bool brtn = false;
461 #if 0
462 /* just search for the two attrs we want */
463 UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr};
464 SecKeychainAttributeInfo attrInfo;
465 attrInfo.count = 2;
466 attrInfo.tag = tags;
467 attrInfo.format = NULL;
468 SecKeychainAttributeList *attrList = NULL;
469 SecKeychainAttribute *attr1 = NULL;
470 SecKeychainAttribute *attr2 = NULL;
471
472 OSStatus ortn = SecKeychainItemCopyAttributesAndData(
473 (SecKeychainItemRef)certRef,
474 &attrInfo,
475 NULL, // itemClass
476 &attrList,
477 NULL, // length - don't need the data
478 NULL); // outData
479 if(ortn) {
480 cssmPerror("SecKeychainItemCopyAttributesAndData", ortn);
481 /* may want to be a bit more robust here, but this should
482 * never happen */
483 return false;
484 }
485 /* subsequent errors to errOut: */
486
487 if((attrList == NULL) || (attrList->count != 2)) {
488 printf("***Unexpected result fetching label attr\n");
489 goto errOut;
490 }
491
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) {
497 brtn = true;
498 }
499 }
500 errOut:
501 SecKeychainItemFreeAttributesAndData(attrList, NULL);
502 #endif
503 return brtn;
504 }
505 #endif
506
507 #if 0
508 /*
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().
512 */
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
518 {
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
526 CFIndex numResCerts;
527
528 certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
529 CFArrayAppendValue(certArray, identity);
530
531 /*
532 * Case 1: identity is a root; we're done. Note that this case
533 * overrides the includeRoot argument.
534 */
535 SecCertificateRef certRef;
536 OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef);
537 if(ortn) {
538 /* should never happen */
539 cssmPerror("SecIdentityCopyCertificate", ortn);
540 return ortn;
541 }
542 bool isRoot = isCertRefRoot(certRef);
543 if(isRoot) {
544 *outArray = certArray;
545 CFRelease(certRef);
546 return errSecSuccess;
547 }
548
549 /*
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.)
554 */
555 CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
556 CFArraySetValueAtIndex(subjCerts, 0, certRef);
557
558 /* the array owns the subject cert ref now */
559 CFRelease(certRef);
560
561 /* Get a SecPolicyRef for generic X509 cert chain verification */
562 ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
563 &CSSMOID_APPLE_X509_BASIC,
564 NULL, // value
565 &policySearch);
566 if(ortn) {
567 cssmPerror("SecPolicySearchCreate", ortn);
568 goto errOut;
569 }
570 ortn = SecPolicySearchCopyNext(policySearch, &policy);
571 if(ortn) {
572 cssmPerror("SecPolicySearchCopyNext", ortn);
573 goto errOut;
574 }
575
576 /* build a SecTrustRef for specified policy and certs */
577 ortn = SecTrustCreateWithCertificates(subjCerts,
578 policy, &secTrust);
579 if(ortn) {
580 cssmPerror("SecTrustCreateWithCertificates", ortn);
581 goto errOut;
582 }
583
584 if(trustedAnchor) {
585 /*
586 * Tell SecTrust to trust this one in addition to the current
587 * trusted system-wide anchors.
588 */
589 CFMutableArrayRef newAnchors;
590 CFArrayRef currAnchors;
591
592 ortn = SecTrustCopyAnchorCertificates(&currAnchors);
593 if(ortn) {
594 /* should never happen */
595 cssmPerror("SecTrustCopyAnchorCertificates", ortn);
596 goto errOut;
597 }
598 newAnchors = CFArrayCreateMutableCopy(NULL,
599 CFArrayGetCount(currAnchors) + 1,
600 currAnchors);
601 CFRelease(currAnchors);
602 CFArrayAppendValue(newAnchors, trustedAnchor);
603 ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
604 CFRelease(newAnchors);
605 if(ortn) {
606 cssmPerror("SecTrustSetAnchorCertificates", ortn);
607 goto errOut;
608 }
609 }
610 /* evaluate: GO */
611 ortn = SecTrustEvaluate(secTrust, &secTrustResult);
612 if(ortn) {
613 cssmPerror("SecTrustEvaluate", ortn);
614 goto errOut;
615 }
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 */
621 break;
622 default:
623 /*
624 * Cert chain construction failed.
625 * Just go with the single subject cert we were given.
626 */
627 printf("***Warning: could not construct completed cert chain\n");
628 ortn = errSecSuccess;
629 goto errOut;
630 }
631
632 /* get resulting constructed cert chain */
633 ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
634 if(ortn) {
635 cssmPerror("SecTrustEvaluate", ortn);
636 goto errOut;
637 }
638
639 /*
640 * Copy certs from constructed chain to our result array, skipping
641 * the leaf (which is already there, as a SecIdentityRef) and possibly
642 * a root.
643 */
644 numResCerts = CFArrayGetCount(certChain);
645 if(numResCerts < 2) {
646 /*
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().
650 */
651 printf("***sslCompleteCertChain screwup: numResCerts %d\n",
652 (int)numResCerts);
653 ortn = errSecSuccess;
654 goto errOut;
655 }
656 if(!includeRoot) {
657 /* skip the last (root) cert) */
658 numResCerts--;
659 }
660 for(CFIndex dex=1; dex<numResCerts; dex++) {
661 certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
662 CFArrayAppendValue(certArray, certRef);
663 }
664 errOut:
665 /* clean up */
666 if(secTrust) {
667 CFRelease(secTrust);
668 }
669 if(subjCerts) {
670 CFRelease(subjCerts);
671 }
672 if(policy) {
673 CFRelease(policy);
674 }
675 if(policySearch) {
676 CFRelease(policySearch);
677 }
678 *outArray = certArray;
679 return ortn;
680 }
681
682
683 /*
684 * Given an open keychain, find a SecIdentityRef and munge it into
685 * a CFArrayRef required by SSLSetCertificate().
686 */
687 CFArrayRef sslKcRefToCertArray(
688 SecKeychainRef kcRef,
689 bool encryptOnly,
690 bool completeCertChain,
691 const char *trustedAnchorFile)
692 {
693 /* quick check to make sure the keychain exists */
694 SecKeychainStatus kcStat;
695 OSStatus ortn = SecKeychainGetStatus(kcRef, &kcStat);
696 if(ortn) {
697 printSslErrStr("SecKeychainGetStatus", ortn);
698 printf("Can not open keychain. Aborting.\n");
699 return nil;
700 }
701
702 /*
703 * Search for "any" identity matching specified key use;
704 * in this app, we expect there to be exactly one.
705 */
706 SecIdentitySearchRef srchRef = nil;
707 ortn = SecIdentitySearchCreate(kcRef,
708 encryptOnly ? CSSM_KEYUSE_DECRYPT : CSSM_KEYUSE_SIGN,
709 &srchRef);
710 if(ortn) {
711 printf("SecIdentitySearchCreate returned %d.\n", (int)ortn);
712 printf("Cannot find signing key in keychain. Aborting.\n");
713 return nil;
714 }
715 SecIdentityRef identity = nil;
716 ortn = SecIdentitySearchCopyNext(srchRef, &identity);
717 if(ortn) {
718 printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn);
719 printf("Cannot find signing key in keychain. Aborting.\n");
720 return nil;
721 }
722 if(CFGetTypeID(identity) != SecIdentityGetTypeID()) {
723 printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
724 return nil;
725 }
726
727 /*
728 * Found one.
729 */
730 if(completeCertChain) {
731 /*
732 * Place it and the other certs needed to verify it -
733 * up to but not including the root - in a CFArray.
734 */
735 SecCertificateRef anchorCert = NULL;
736 if(trustedAnchorFile) {
737 ortn = sslReadAnchor(trustedAnchorFile, &anchorCert);
738 if(ortn) {
739 printf("***Error reading anchor file\n");
740 }
741 }
742 CFArrayRef ca;
743 ortn = sslCompleteCertChain(identity, anchorCert, false, &ca);
744 if(anchorCert) {
745 CFRelease(anchorCert);
746 }
747 return ca;
748 }
749 else {
750 /* simple case, just this one identity */
751 CFArrayRef ca = CFArrayCreate(NULL,
752 (const void **)&identity,
753 1,
754 NULL);
755 if(ca == nil) {
756 printf("CFArrayCreate error\n");
757 }
758 return ca;
759 }
760 }
761 #endif
762
763 OSStatus addTrustedSecCert(
764 SSLContextRef ctx,
765 SecCertificateRef secCert,
766 bool replaceAnchors)
767 {
768 OSStatus ortn;
769 CFMutableArrayRef array;
770
771 if(secCert == NULL) {
772 printf("***addTrustedSecCert screwup\n");
773 return errSecParam;
774 }
775 array = CFArrayCreateMutable(kCFAllocatorDefault,
776 (CFIndex)1, &kCFTypeArrayCallBacks);
777 if(array == NULL) {
778 return errSecAllocate;
779 }
780 CFArrayAppendValue(array, secCert);
781 ortn = SSLSetTrustedRoots(ctx, array, replaceAnchors ? true : false);
782 if(ortn) {
783 printSslErrStr("SSLSetTrustedRoots", ortn);
784 }
785 CFRelease(array);
786 return ortn;
787 }
788
789 #if 0
790 OSStatus sslReadAnchor(
791 const char *anchorFile,
792 SecCertificateRef *certRef)
793 {
794 OSStatus ortn;
795 SecCertificateRef secCert;
796 unsigned char *certData;
797 unsigned certLen;
798 CSSM_DATA cert;
799
800 if(readFile(anchorFile, &certData, &certLen)) {
801 return -1;
802 }
803 cert.Data = certData;
804 cert.Length = certLen;
805 ortn = SecCertificateCreateFromData(&cert,
806 CSSM_CERT_X_509v3,
807 CSSM_CERT_ENCODING_DER,
808 &secCert);
809 free(certData);
810 if(ortn) {
811 printf("***SecCertificateCreateFromData returned %d\n", (int)ortn);
812 return ortn;
813 }
814 *certRef = secCert;
815 return errSecSuccess;
816 }
817 #endif
818
819 OSStatus sslAddTrustedRoot(
820 SSLContextRef ctx,
821 const char *anchorFile,
822 bool replaceAnchors)
823 {
824 #if 0
825 OSStatus ortn;
826 SecCertificateRef secCert;
827
828 ortn = sslReadAnchor(anchorFile, &secCert);
829 if(ortn) {
830 printf("***Error reading %s. SSLSetTrustedRoots skipped.\n",
831 anchorFile);
832 return ortn;
833 }
834 return addTrustedSecCert(ctx, secCert, replaceAnchors);
835 #else
836 return 0;
837 #endif
838 }
839
840 #if 0
841 /* Per 3537606 this is no longer necessary */
842 /*
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.
847 */
848 OSStatus addIdentityAsTrustedRoot(
849 SSLContextRef ctx,
850 CFArrayRef identArray)
851 {
852 CFIndex numItems = CFArrayGetCount(identArray);
853 if(numItems == 0) {
854 printf("***addIdentityAsTrustedRoot: empty identArray\n");
855 return errSecParam;
856 }
857
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()) {
861 /* identity */
862 SecCertificateRef certRef;
863 OSStatus ortn = SecIdentityCopyCertificate(
864 (SecIdentityRef)theItem, &certRef);
865 if(ortn) {
866 cssmPerror("SecIdentityCopyCertificate", ortn);
867 printf("***Error gettting cert from identity\n");
868 return ortn;
869 }
870 ortn = addTrustedSecCert(ctx, certRef, false);
871 CFRelease(certRef);
872 return ortn;
873 }
874 else if(CFGetTypeID(theItem) == SecCertificateGetTypeID()) {
875 /* certificate */
876 return addTrustedSecCert(ctx, (SecCertificateRef)theItem, false);
877 }
878 else {
879 printf("***Bogus item in identity array\n");
880 return errSecParam;
881 }
882 }
883 #else
884 OSStatus addIdentityAsTrustedRoot(
885 SSLContextRef ctx,
886 CFArrayRef identArray)
887 {
888 return errSecSuccess;
889 }
890 #endif
891
892 /*
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.
896 */
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
908 };
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
918 };
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
927 };
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
937 };
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
943 };
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
948 };
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
953 };
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
962 };
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
971 };
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
1001 };
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
1011 };
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
1024 };
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
1037 };
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
1075 };
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
1083 };
1084
1085
1086 /*
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.
1090 */
1091 OSStatus sslSetEnabledCiphers(
1092 SSLContextRef ctx,
1093 const SSLCipherSuite *ciphers)
1094 {
1095 size_t numSupported;
1096 OSStatus ortn;
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
1102
1103 /* first get all the supported ciphers */
1104 ortn = SSLGetNumberSupportedCiphers(ctx, &numSupported);
1105 if(ortn) {
1106 printSslErrStr("SSLGetNumberSupportedCiphers", ortn);
1107 return ortn;
1108 }
1109 supported = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1110 ortn = SSLGetSupportedCiphers(ctx, supported, &numSupported);
1111 if(ortn) {
1112 printSslErrStr("SSLGetSupportedCiphers", ortn);
1113 return ortn;
1114 }
1115
1116 /*
1117 * Malloc an array we'll use for SSLGetEnabledCiphers - this will be
1118 * bigger than the number of suites we actually specify
1119 */
1120 enabled = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1121
1122 /*
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
1125 * enabled.
1126 */
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];
1131 break;
1132 }
1133 }
1134 }
1135
1136 /* send it on down. */
1137 ortn = SSLSetEnabledCiphers(ctx, enabled, enabledDex);
1138 if(ortn) {
1139 printSslErrStr("SSLSetEnabledCiphers", ortn);
1140 }
1141 free(enabled);
1142 free(supported);
1143 return ortn;
1144 }
1145
1146 /*
1147 * Specify a restricted set of cipherspecs.
1148 */
1149 OSStatus sslSetCipherRestrictions(
1150 SSLContextRef ctx,
1151 char cipherRestrict)
1152 {
1153 OSStatus ortn;
1154
1155 if(cipherRestrict == '\0') {
1156 return errSecSuccess; // actually should not have been called
1157 }
1158 switch(cipherRestrict) {
1159 case 'e':
1160 ortn = sslSetEnabledCiphers(ctx, suites40);
1161 break;
1162 case 'd':
1163 ortn = sslSetEnabledCiphers(ctx, suitesDES);
1164 break;
1165 case 'D':
1166 ortn = sslSetEnabledCiphers(ctx, suitesDES40);
1167 break;
1168 case '3':
1169 ortn = sslSetEnabledCiphers(ctx, suites3DES);
1170 break;
1171 case '4':
1172 ortn = sslSetEnabledCiphers(ctx, suitesRC4);
1173 break;
1174 case '$':
1175 ortn = sslSetEnabledCiphers(ctx, suitesRC4_40);
1176 break;
1177 case '2':
1178 ortn = sslSetEnabledCiphers(ctx, suitesRC2);
1179 break;
1180 case 'a':
1181 ortn = sslSetEnabledCiphers(ctx, suitesAES128);
1182 break;
1183 case 'A':
1184 ortn = sslSetEnabledCiphers(ctx, suitesAES256);
1185 break;
1186 case 'h':
1187 ortn = sslSetEnabledCiphers(ctx, suitesDH);
1188 break;
1189 case 'H':
1190 ortn = sslSetEnabledCiphers(ctx, suitesDHAnon);
1191 break;
1192 case 'r':
1193 ortn = sslSetEnabledCiphers(ctx, suitesDH_RSA);
1194 break;
1195 case 's':
1196 ortn = sslSetEnabledCiphers(ctx, suitesDH_DSS);
1197 break;
1198 default:
1199 printf("***bad cipherSpec***\n");
1200 exit(1);
1201 }
1202 return ortn;
1203 }
1204
1205 #if 0
1206 int sslVerifyClientCertState(
1207 char *whichSide, // "client" or "server"
1208 SSLClientCertificateState expectState,
1209 SSLClientCertificateState gotState)
1210 {
1211 if(expectState == SSL_CLIENT_CERT_IGNORE) {
1212 /* app says "don't bopther checking" */
1213 return 0;
1214 }
1215 if(expectState == gotState) {
1216 return 0;
1217 }
1218 printf("***%s: Expected clientCertState %s; got %s\n", whichSide,
1219 sslGetClientCertStateString(expectState),
1220 sslGetClientCertStateString(gotState));
1221 return 1;
1222 }
1223
1224 int sslVerifyRtn(
1225 char *whichSide, // "client" or "server"
1226 OSStatus expectRtn,
1227 OSStatus gotRtn)
1228 {
1229 if(expectRtn == gotRtn) {
1230 return 0;
1231 }
1232 printf("***%s: Expected return %s; got %s\n", whichSide,
1233 sslGetSSLErrString(expectRtn),
1234 sslGetSSLErrString(gotRtn));
1235 return 1;
1236 }
1237
1238 int sslVerifyProtVers(
1239 char *whichSide, // "client" or "server"
1240 SSLProtocol expectProt,
1241 SSLProtocol gotProt)
1242 {
1243 if(expectProt == SSL_PROTOCOL_IGNORE) {
1244 /* app says "don't bopther checking" */
1245 return 0;
1246 }
1247 if(expectProt == gotProt) {
1248 return 0;
1249 }
1250 printf("***%s: Expected return %s; got %s\n", whichSide,
1251 sslGetProtocolVersionString(expectProt),
1252 sslGetProtocolVersionString(gotProt));
1253 return 1;
1254 }
1255
1256 int sslVerifyCipher(
1257 char *whichSide, // "client" or "server"
1258 SSLCipherSuite expectCipher,
1259 SSLCipherSuite gotCipher)
1260 {
1261 if(expectCipher == SSL_CIPHER_IGNORE) {
1262 /* app says "don't bopther checking" */
1263 return 0;
1264 }
1265 if(expectCipher == gotCipher) {
1266 return 0;
1267 }
1268 printf("***%s: Expected return %s; got %s\n", whichSide,
1269 sslGetCipherSuiteString(expectCipher),
1270 sslGetCipherSuiteString(gotCipher));
1271 return 1;
1272 }
1273
1274
1275 OSStatus sslSetProtocols(
1276 SSLContextRef ctx,
1277 const char *acceptedProts,
1278 SSLProtocol tryVersion) // only used if acceptedProts NULL
1279 {
1280 OSStatus ortn;
1281
1282 if(acceptedProts) {
1283 #if JAGUAR_BUILD
1284 printf("***SSLSetProtocolVersionEnabled not supported in this config.\n");
1285 exit(1);
1286 #endif
1287 ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false);
1288 if(ortn) {
1289 printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn);
1290 return ortn;
1291 }
1292 for(const char *cp = acceptedProts; *cp; cp++) {
1293 SSLProtocol prot;
1294 switch(*cp) {
1295 case '2':
1296 prot = kSSLProtocol2;
1297 break;
1298 case '3':
1299 prot = kSSLProtocol3;
1300 break;
1301 case 't':
1302 prot = kTLSProtocol1;
1303 break;
1304 default:
1305 printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts);
1306 exit(1);
1307 }
1308 ortn = SSLSetProtocolVersionEnabled(ctx, prot, true);
1309 if(ortn) {
1310 printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
1311 return ortn;
1312 }
1313 }
1314 }
1315 else {
1316 ortn = SSLSetProtocolVersion(ctx, tryVersion);
1317 if(ortn) {
1318 printSslErrStr("SSLSetProtocolVersion", ortn);
1319 return ortn;
1320 }
1321 }
1322 return errSecSuccess;
1323 }
1324
1325 void sslShowResult(
1326 char *whichSide, // "client" or "server"
1327 SslAppTestParams *params)
1328 {
1329 printf("%s status:\n", whichSide);
1330 if(params->acceptedProts) {
1331 printf(" Allowed SSL versions : %s\n", params->acceptedProts);
1332 }
1333 else {
1334 printf(" Attempted SSL version : %s\n",
1335 sslGetProtocolVersionString(params->tryVersion));
1336 }
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));
1345 }
1346 }
1347 #endif
1348
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
1352
1353 void sslOutputDot()
1354 {
1355 time_t thisTime = time(0);
1356
1357 if((thisTime - lastTime) >= TIME_INTERVAL) {
1358 printf("."); fflush(stdout);
1359 lastTime = thisTime;
1360 }
1361 }
1362
1363 #if 0
1364 /* main server pthread body */
1365 static void *sslServerThread(void *arg)
1366 {
1367 SslAppTestParams *testParams = (SslAppTestParams *)arg;
1368 OSStatus status;
1369
1370 status = sslAppServe(testParams);
1371 pthread_exit((void*)status);
1372 /* NOT REACHED */
1373 return (void *)status;
1374 }
1375
1376 /*
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.
1382 */
1383 #define CLIENT_WAIT_SECONDS 1
1384 int sslRunSession(
1385 SslAppTestParams*serverParams,
1386 SslAppTestParams *clientParams,
1387 const char *testDesc)
1388 {
1389 pthread_t serverPthread;
1390 OSStatus clientRtn;
1391 void *serverRtn;
1392
1393 if(testDesc && !clientParams->quiet) {
1394 printf("===== %s =====\n", testDesc);
1395 }
1396
1397 if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) {
1398 printf("***Error initializing mutex; aborting.\n");
1399 return -1;
1400 }
1401 if(pthread_cond_init(&serverParams->pthreadCond, NULL)) {
1402 printf("***Error initializing pthreadCond; aborting.\n");
1403 return -1;
1404 }
1405 serverParams->serverReady = false; // server sets true
1406
1407 int result = pthread_create(&serverPthread, NULL,
1408 sslServerThread, serverParams);
1409 if(result) {
1410 printf("***Error starting up server thread; aborting.\n");
1411 return result;
1412 }
1413
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");
1417 return -1;
1418 }
1419 while(!serverParams->serverReady) {
1420 if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) {
1421 printf("***Error waiting server thread; aborting.\n");
1422 return -1;
1423 }
1424 }
1425 pthread_mutex_unlock(&serverParams->pthreadMutex);
1426 pthread_cond_destroy(&serverParams->pthreadCond);
1427 pthread_mutex_destroy(&serverParams->pthreadMutex);
1428
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);
1434 if(result) {
1435 printf("***pthread_join returned %d, aborting\n", result);
1436 return result;
1437 }
1438
1439 if(serverParams->verbose) {
1440 sslShowResult("server", serverParams);
1441 }
1442 if(clientParams->verbose) {
1443 sslShowResult("client", clientParams);
1444 }
1445
1446 /* verify results */
1447 int ourRtn = 0;
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);
1461 }
1462 if(clientParams->ortn == errSecSuccess) {
1463 ourRtn += sslVerifyCipher("client", clientParams->expectCipher,
1464 clientParams->negCipher);
1465 }
1466 return ourRtn;
1467 }
1468
1469 static bool isCertRoot(
1470 SecCertificateRef cert)
1471 {
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;
1476 OSStatus ortn;
1477 ... */
1478 return true;
1479 }
1480
1481 /*
1482 * Add all of the roots in a given KC to SSL ctx's trusted anchors.
1483 */
1484 OSStatus sslAddTrustedRoots(
1485 SSLContextRef ctx,
1486 SecKeychainRef keychain,
1487 bool *foundOne) // RETURNED, true if we found
1488 // at least one root cert
1489 {
1490 OSStatus ortn;
1491 SecCertificateRef secCert;
1492 SecKeychainSearchRef srch;
1493
1494 *foundOne = false;
1495 ortn = SecKeychainSearchCreateFromAttributes(keychain,
1496 kSecCertificateItemClass,
1497 NULL, // any attrs
1498 &srch);
1499 if(ortn) {
1500 printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn);
1501 return ortn;
1502 }
1503
1504 /*
1505 * Only use root certs. Not an error if we don't find any.
1506 */
1507 do {
1508 ortn = SecKeychainSearchCopyNext(srch,
1509 (SecKeychainItemRef *)&secCert);
1510 if(ortn) {
1511 break;
1512 }
1513
1514 /* see if it's a root */
1515 if(!isCertRoot(secCert)) {
1516 continue;
1517 }
1518
1519 /* Tell Secure Transport to trust this one. */
1520 ortn = addTrustedSecCert(ctx, secCert, false);
1521 if(ortn) {
1522 /* fatal */
1523 printSslErrStr("addTrustedSecCert", ortn);
1524 return ortn;
1525 }
1526 CFRelease(secCert);
1527 *foundOne = true;
1528 } while(ortn == errSecSuccess);
1529 CFRelease(srch);
1530 return errSecSuccess;
1531 }
1532
1533 /*
1534 * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename.
1535 */
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
1542 {
1543 SecCertificateRef trustedCert = NULL;
1544 OSStatus ortn;
1545
1546 if(trustedAnchor) {
1547 ortn = sslReadAnchor(trustedAnchor, &trustedCert);
1548 if(ortn) {
1549 printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n",
1550 trustedAnchor);
1551 trustedCert = NULL;
1552 }
1553 }
1554 ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, outArray);
1555 if(trustedCert) {
1556 CFRelease(trustedCert);
1557 }
1558 return ortn;
1559 }
1560
1561 /*
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.
1567 */
1568 void sslKeychainPath(
1569 const char *kcName,
1570 char *kcPath) // allocd by caller, MAXPATHLEN
1571 {
1572 if(kcName[0] == '\0') {
1573 kcPath[0] = '\0';
1574 }
1575 else if(geteuid() == 0) {
1576 /* root */
1577 sprintf(kcPath, "/Library/Keychains/%s", kcName);
1578 }
1579 else {
1580 /* user, leave alone */
1581 strcpy(kcPath, kcName);
1582 }
1583 }
1584
1585 /* Verify presence of required file. Returns nonzero if not found. */
1586 int sslCheckFile(const char *path)
1587 {
1588 struct stat sb;
1589
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");
1594 return 1;
1595 }
1596 return 0;
1597 }
1598
1599 #endif
1600
1601 /* Stringify a SSL_ECDSA_NamedCurve */
1602 extern const char *sslCurveString(
1603 SSL_ECDSA_NamedCurve namedCurve)
1604 {
1605 static char unk[100];
1606
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";
1612 default:
1613 sprintf(unk, "Unknown <%d>", (int)namedCurve);
1614 return unk;
1615 }
1616 }