]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/clAppUtils/sslAppUtils.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / SecurityTests / clxutils / clAppUtils / sslAppUtils.cpp
1
2 #include "sslAppUtils.h"
3 #include "sslThreading.h"
4 #include "identPicker.h"
5 #include <utilLib/fileIo.h>
6 #include <utilLib/common.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <sys/param.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
13 #include <Security/AuthSession.h> // for Sec errors
14 #include <CoreFoundation/CFDate.h>
15
16 /* Set true when PR-3074739 is merged to TOT */
17 #define NEW_SSL_ERRS_3074739 1
18
19 const char *sslGetCipherSuiteString(SSLCipherSuite cs)
20 {
21 static char noSuite[40];
22
23 switch(cs) {
24 case SSL_NULL_WITH_NULL_NULL:
25 return "SSL_NULL_WITH_NULL_NULL";
26 case SSL_RSA_WITH_NULL_MD5:
27 return "SSL_RSA_WITH_NULL_MD5";
28 case SSL_RSA_WITH_NULL_SHA:
29 return "SSL_RSA_WITH_NULL_SHA";
30 case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
31 return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
32 case SSL_RSA_WITH_RC4_128_MD5:
33 return "SSL_RSA_WITH_RC4_128_MD5";
34 case SSL_RSA_WITH_RC4_128_SHA:
35 return "SSL_RSA_WITH_RC4_128_SHA";
36 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
37 return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
38 case SSL_RSA_WITH_IDEA_CBC_SHA:
39 return "SSL_RSA_WITH_IDEA_CBC_SHA";
40 case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
41 return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
42 case SSL_RSA_WITH_DES_CBC_SHA:
43 return "SSL_RSA_WITH_DES_CBC_SHA";
44 case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
45 return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
46 case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
47 return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
48 case SSL_DH_DSS_WITH_DES_CBC_SHA:
49 return "SSL_DH_DSS_WITH_DES_CBC_SHA";
50 case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:
51 return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
52 case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
53 return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
54 case SSL_DH_RSA_WITH_DES_CBC_SHA:
55 return "SSL_DH_RSA_WITH_DES_CBC_SHA";
56 case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:
57 return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
58 case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
59 return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
60 case SSL_DHE_DSS_WITH_DES_CBC_SHA:
61 return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
62 case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
63 return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
64 case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
65 return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
66 case SSL_DHE_RSA_WITH_DES_CBC_SHA:
67 return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
68 case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
69 return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
70 case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
71 return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
72 case SSL_DH_anon_WITH_RC4_128_MD5:
73 return "SSL_DH_anon_WITH_RC4_128_MD5";
74 case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
75 return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
76 case SSL_DH_anon_WITH_DES_CBC_SHA:
77 return "SSL_DH_anon_WITH_DES_CBC_SHA";
78 case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
79 return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
80 case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
81 return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
82 case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
83 return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
84 case SSL_RSA_WITH_RC2_CBC_MD5:
85 return "SSL_RSA_WITH_RC2_CBC_MD5";
86 case SSL_RSA_WITH_IDEA_CBC_MD5:
87 return "SSL_RSA_WITH_IDEA_CBC_MD5";
88 case SSL_RSA_WITH_DES_CBC_MD5:
89 return "SSL_RSA_WITH_DES_CBC_MD5";
90 case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
91 return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
92 case SSL_NO_SUCH_CIPHERSUITE:
93 return "SSL_NO_SUCH_CIPHERSUITE";
94 case TLS_RSA_WITH_AES_128_CBC_SHA:
95 return "TLS_RSA_WITH_AES_128_CBC_SHA";
96 case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
97 return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
98 case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
99 return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
100 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
101 return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
102 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
103 return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
104 case TLS_DH_anon_WITH_AES_128_CBC_SHA:
105 return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
106 case TLS_RSA_WITH_AES_256_CBC_SHA:
107 return "TLS_RSA_WITH_AES_256_CBC_SHA";
108 case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
109 return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
110 case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
111 return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
112 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
113 return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
114 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
115 return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
116 case TLS_DH_anon_WITH_AES_256_CBC_SHA:
117 return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
118
119 /* ECDSA */
120 case TLS_ECDH_ECDSA_WITH_NULL_SHA:
121 return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
122 case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
123 return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
124 case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
125 return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
126 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
127 return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
128 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
129 return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
130 case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
131 return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
132 case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
133 return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
134 case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
135 return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
136 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
137 return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
138 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
139 return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
140 case TLS_ECDH_RSA_WITH_NULL_SHA:
141 return "TLS_ECDH_RSA_WITH_NULL_SHA";
142 case TLS_ECDH_RSA_WITH_RC4_128_SHA:
143 return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
144 case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
145 return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
146 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
147 return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
148 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
149 return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
150 case TLS_ECDHE_RSA_WITH_NULL_SHA:
151 return "TLS_ECDHE_RSA_WITH_NULL_SHA";
152 case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
153 return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
154 case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
155 return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
156 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
157 return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
158 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
159 return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
160 case TLS_ECDH_anon_WITH_NULL_SHA:
161 return "TLS_ECDH_anon_WITH_NULL_SHA";
162 case TLS_ECDH_anon_WITH_RC4_128_SHA:
163 return "TLS_ECDH_anon_WITH_RC4_128_SHA";
164 case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
165 return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
166 case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
167 return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
168 case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
169 return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
170
171 default:
172 sprintf(noSuite, "Unknown (%d)", (unsigned)cs);
173 return noSuite;
174 }
175 }
176
177 /*
178 * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion -
179 * return a string representation.
180 */
181 const char *sslGetProtocolVersionString(SSLProtocol prot)
182 {
183 static char noProt[20];
184
185 switch(prot) {
186 case kSSLProtocolUnknown:
187 return "kSSLProtocolUnknown";
188 case kSSLProtocol2:
189 return "kSSLProtocol2";
190 case kSSLProtocol3:
191 return "kSSLProtocol3";
192 case kSSLProtocol3Only:
193 return "kSSLProtocol3Only";
194 case kTLSProtocol1:
195 return "kTLSProtocol1";
196 case kTLSProtocol1Only:
197 return "kTLSProtocol1Only";
198 default:
199 sprintf(noProt, "Unknown (%d)", (unsigned)prot);
200 return noProt;
201 }
202 }
203
204 /*
205 * Return string representation of SecureTransport-related OSStatus.
206 */
207 const char *sslGetSSLErrString(OSStatus err)
208 {
209 static char noErrStr[20];
210
211 switch(err) {
212 case noErr:
213 return "noErr";
214 case memFullErr:
215 return "memFullErr";
216 case paramErr:
217 return "paramErr";
218 case unimpErr:
219 return "unimpErr";
220 case ioErr:
221 return "ioErr";
222 case badReqErr:
223 return "badReqErr";
224 case errSSLProtocol:
225 return "errSSLProtocol";
226 case errSSLNegotiation:
227 return "errSSLNegotiation";
228 case errSSLFatalAlert:
229 return "errSSLFatalAlert";
230 case errSSLWouldBlock:
231 return "errSSLWouldBlock";
232 case errSSLSessionNotFound:
233 return "errSSLSessionNotFound";
234 case errSSLClosedGraceful:
235 return "errSSLClosedGraceful";
236 case errSSLClosedAbort:
237 return "errSSLClosedAbort";
238 case errSSLXCertChainInvalid:
239 return "errSSLXCertChainInvalid";
240 case errSSLBadCert:
241 return "errSSLBadCert";
242 case errSSLCrypto:
243 return "errSSLCrypto";
244 case errSSLInternal:
245 return "errSSLInternal";
246 case errSSLModuleAttach:
247 return "errSSLModuleAttach";
248 case errSSLUnknownRootCert:
249 return "errSSLUnknownRootCert";
250 case errSSLNoRootCert:
251 return "errSSLNoRootCert";
252 case errSSLCertExpired:
253 return "errSSLCertExpired";
254 case errSSLCertNotYetValid:
255 return "errSSLCertNotYetValid";
256 case errSSLClosedNoNotify:
257 return "errSSLClosedNoNotify";
258 case errSSLBufferOverflow:
259 return "errSSLBufferOverflow";
260 case errSSLBadCipherSuite:
261 return "errSSLBadCipherSuite";
262 /* TLS/Panther addenda */
263 case errSSLPeerUnexpectedMsg:
264 return "errSSLPeerUnexpectedMsg";
265 case errSSLPeerBadRecordMac:
266 return "errSSLPeerBadRecordMac";
267 case errSSLPeerDecryptionFail:
268 return "errSSLPeerDecryptionFail";
269 case errSSLPeerRecordOverflow:
270 return "errSSLPeerRecordOverflow";
271 case errSSLPeerDecompressFail:
272 return "errSSLPeerDecompressFail";
273 case errSSLPeerHandshakeFail:
274 return "errSSLPeerHandshakeFail";
275 case errSSLPeerBadCert:
276 return "errSSLPeerBadCert";
277 case errSSLPeerUnsupportedCert:
278 return "errSSLPeerUnsupportedCert";
279 case errSSLPeerCertRevoked:
280 return "errSSLPeerCertRevoked";
281 case errSSLPeerCertExpired:
282 return "errSSLPeerCertExpired";
283 case errSSLPeerCertUnknown:
284 return "errSSLPeerCertUnknown";
285 case errSSLIllegalParam:
286 return "errSSLIllegalParam";
287 case errSSLPeerUnknownCA:
288 return "errSSLPeerUnknownCA";
289 case errSSLPeerAccessDenied:
290 return "errSSLPeerAccessDenied";
291 case errSSLPeerDecodeError:
292 return "errSSLPeerDecodeError";
293 case errSSLPeerDecryptError:
294 return "errSSLPeerDecryptError";
295 case errSSLPeerExportRestriction:
296 return "errSSLPeerExportRestriction";
297 case errSSLPeerProtocolVersion:
298 return "errSSLPeerProtocolVersion";
299 case errSSLPeerInsufficientSecurity:
300 return "errSSLPeerInsufficientSecurity";
301 case errSSLPeerInternalError:
302 return "errSSLPeerInternalError";
303 case errSSLPeerUserCancelled:
304 return "errSSLPeerUserCancelled";
305 case errSSLPeerNoRenegotiation:
306 return "errSSLPeerNoRenegotiation";
307 case errSSLHostNameMismatch:
308 return "errSSLHostNameMismatch";
309 case errSSLConnectionRefused:
310 return "errSSLConnectionRefused";
311 case errSSLDecryptionFail:
312 return "errSSLDecryptionFail";
313 case errSSLBadRecordMac:
314 return "errSSLBadRecordMac";
315 case errSSLRecordOverflow:
316 return "errSSLRecordOverflow";
317 case errSSLBadConfiguration:
318 return "errSSLBadConfiguration";
319
320 /* some from the Sec layer */
321 case errSecNotAvailable: return "errSecNotAvailable";
322 case errSecReadOnly: return "errSecReadOnly";
323 case errSecAuthFailed: return "errSecAuthFailed";
324 case errSecNoSuchKeychain: return "errSecNoSuchKeychain";
325 case errSecInvalidKeychain: return "errSecInvalidKeychain";
326 case errSecDuplicateItem: return "errSecDuplicateItem";
327 case errSecItemNotFound: return "errSecItemNotFound";
328 case errSecNoSuchAttr: return "errSecNoSuchAttr";
329 case errSecInvalidItemRef: return "errSecInvalidItemRef";
330 case errSecInvalidSearchRef: return "errSecInvalidSearchRef";
331 case errSecNoSuchClass: return "errSecNoSuchClass";
332 case errSecNoDefaultKeychain: return "errSecNoDefaultKeychain";
333 case errSecWrongSecVersion: return "errSecWrongSecVersion";
334 case errSessionInvalidId: return "errSessionInvalidId";
335 case errSessionInvalidAttributes: return "errSessionInvalidAttributes";
336 case errSessionAuthorizationDenied: return "errSessionAuthorizationDenied";
337 case errSessionInternal: return "errSessionInternal";
338 case errSessionInvalidFlags: return "errSessionInvalidFlags";
339 case errSecInvalidTrustSettings: return "errSecInvalidTrustSettings";
340 case errSecNoTrustSettings: return "errSecNoTrustSettings";
341
342 default:
343 if(err < (CSSM_BASE_ERROR +
344 (CSSM_ERRORCODE_MODULE_EXTENT * 8))) {
345 /* assume CSSM error */
346 return cssmErrToStr(err);
347 }
348 else {
349 sprintf(noErrStr, "Unknown (%d)", (unsigned)err);
350 return noErrStr;
351 }
352 }
353 }
354
355 void printSslErrStr(
356 const char *op,
357 OSStatus err)
358 {
359 printf("*** %s: %s\n", op, sslGetSSLErrString(err));
360 }
361
362 const char *sslGetClientCertStateString(SSLClientCertificateState state)
363 {
364 static char noState[20];
365
366 switch(state) {
367 case kSSLClientCertNone:
368 return "ClientCertNone";
369 case kSSLClientCertRequested:
370 return "CertRequested";
371 case kSSLClientCertSent:
372 return "ClientCertSent";
373 case kSSLClientCertRejected:
374 return "ClientCertRejected";
375 default:
376 sprintf(noState, "Unknown (%d)", (unsigned)state);
377 return noState;
378 }
379
380 }
381
382 const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType)
383 {
384 static char noType[20];
385
386 switch(authType) {
387 case SSLClientAuthNone:
388 return "None";
389 case SSLClientAuth_RSASign:
390 return "RSASign";
391 case SSLClientAuth_DSSSign:
392 return "DSSSign";
393 case SSLClientAuth_RSAFixedDH:
394 return "RSAFixedDH";
395 case SSLClientAuth_DSS_FixedDH:
396 return "DSS_FixedDH";
397 case SSLClientAuth_ECDSASign:
398 return "ECDSASign";
399 case SSLClientAuth_RSAFixedECDH:
400 return "RSAFixedECDH";
401 case SSLClientAuth_ECDSAFixedECDH:
402 return "ECDSAFixedECDH";
403 default:
404 sprintf(noType, "Unknown (%d)", (unsigned)authType);
405 return noType;
406 }
407 }
408
409 /*
410 * Convert a keychain name (which may be NULL) into the CFArrayRef required
411 * by SSLSetCertificate. This is a bare-bones example of this operation,
412 * since it requires and assumes that there is exactly one SecIdentity
413 * in the keychain - i.e., there is exactly one matching cert/private key
414 * pair. A real world server would probably search a keychain for a SecIdentity
415 * matching some specific criteria.
416 */
417 CFArrayRef getSslCerts(
418 const char *kcName, // may be NULL, i.e., use default
419 CSSM_BOOL encryptOnly,
420 CSSM_BOOL completeCertChain,
421 const char *anchorFile, // optional trusted anchor
422 SecKeychainRef *pKcRef) // RETURNED
423 {
424 SecKeychainRef kcRef = nil;
425 OSStatus ortn;
426
427 *pKcRef = nil;
428
429 /* pick a keychain */
430 if(kcName) {
431 ortn = SecKeychainOpen(kcName, &kcRef);
432 if(ortn) {
433 printf("SecKeychainOpen returned %d.\n", (int)ortn);
434 printf("Cannot open keychain at %s. Aborting.\n", kcName);
435 return NULL;
436 }
437 }
438 else {
439 /* use default keychain */
440 ortn = SecKeychainCopyDefault(&kcRef);
441 if(ortn) {
442 printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn);
443 return nil;
444 }
445 }
446 *pKcRef = kcRef;
447 return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain,
448 NULL, // SSL policy
449 anchorFile);
450 }
451
452 /*
453 * Determine if specified SecCertificateRef is a self-signed cert.
454 * We do this by comparing the subject and issuerr names; no cryptographic
455 * verification is performed.
456 *
457 * Returns true if the cert appears to be a root.
458 */
459 static bool isCertRefRoot(
460 SecCertificateRef certRef)
461 {
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 bool brtn = false;
472
473 OSStatus ortn = SecKeychainItemCopyAttributesAndData(
474 (SecKeychainItemRef)certRef,
475 &attrInfo,
476 NULL, // itemClass
477 &attrList,
478 NULL, // length - don't need the data
479 NULL); // outData
480 if(ortn) {
481 cssmPerror("SecKeychainItemCopyAttributesAndData", ortn);
482 /* may want to be a bit more robust here, but this should
483 * never happen */
484 return false;
485 }
486 /* subsequent errors to errOut: */
487
488 if((attrList == NULL) || (attrList->count != 2)) {
489 printf("***Unexpected result fetching label attr\n");
490 goto errOut;
491 }
492
493 /* rootness is just byte-for-byte compare of the two names */
494 attr1 = &attrList->attr[0];
495 attr2 = &attrList->attr[1];
496 if(attr1->length == attr2->length) {
497 if(memcmp(attr1->data, attr2->data, attr1->length) == 0) {
498 brtn = true;
499 }
500 }
501 errOut:
502 SecKeychainItemFreeAttributesAndData(attrList, NULL);
503 return brtn;
504 }
505
506
507 /*
508 * Given a SecIdentityRef, do our best to construct a complete, ordered, and
509 * verified cert chain, returning the result in a CFArrayRef. The result is
510 * suitable for use when calling SSLSetCertificate().
511 */
512 OSStatus sslCompleteCertChain(
513 SecIdentityRef identity,
514 SecCertificateRef trustedAnchor, // optional additional trusted anchor
515 bool includeRoot, // include the root in outArray
516 const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL
517 CFArrayRef *outArray) // created and RETURNED
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 noErr;
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 SSL cert chain verification */
562 ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
563 vfyPolicy ? vfyPolicy : &CSSMOID_APPLE_TP_SSL,
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 = noErr;
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 = noErr;
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 CSSM_BOOL encryptOnly,
690 CSSM_BOOL completeCertChain,
691 const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL policy to complete
692 const char *trustedAnchorFile)
693 {
694 /* quick check to make sure the keychain exists */
695 SecKeychainStatus kcStat;
696 OSStatus ortn = SecKeychainGetStatus(kcRef, &kcStat);
697 if(ortn) {
698 printSslErrStr("SecKeychainGetStatus", ortn);
699 printf("Can not open keychain. Aborting.\n");
700 return nil;
701 }
702
703 /*
704 * Search for "any" identity matching specified key use;
705 * in this app, we expect there to be exactly one.
706 */
707 SecIdentitySearchRef srchRef = nil;
708 ortn = SecIdentitySearchCreate(kcRef,
709 encryptOnly ? CSSM_KEYUSE_DECRYPT : CSSM_KEYUSE_SIGN,
710 &srchRef);
711 if(ortn) {
712 printf("SecIdentitySearchCreate returned %d.\n", (int)ortn);
713 printf("Cannot find signing key in keychain. Aborting.\n");
714 return nil;
715 }
716 SecIdentityRef identity = nil;
717 ortn = SecIdentitySearchCopyNext(srchRef, &identity);
718 if(ortn) {
719 printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn);
720 printf("Cannot find signing key in keychain. Aborting.\n");
721 return nil;
722 }
723 if(CFGetTypeID(identity) != SecIdentityGetTypeID()) {
724 printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
725 return nil;
726 }
727
728 /*
729 * Found one.
730 */
731 if(completeCertChain) {
732 /*
733 * Place it and the other certs needed to verify it -
734 * up to but not including the root - in a CFArray.
735 */
736 SecCertificateRef anchorCert = NULL;
737 if(trustedAnchorFile) {
738 ortn = sslReadAnchor(trustedAnchorFile, &anchorCert);
739 if(ortn) {
740 printf("***Error reading anchor file\n");
741 }
742 }
743 CFArrayRef ca;
744 ortn = sslCompleteCertChain(identity, anchorCert, false, vfyPolicy, &ca);
745 if(anchorCert) {
746 CFRelease(anchorCert);
747 }
748 return ca;
749 }
750 else {
751 /* simple case, just this one identity */
752 CFArrayRef ca = CFArrayCreate(NULL,
753 (const void **)&identity,
754 1,
755 NULL);
756 if(ca == nil) {
757 printf("CFArrayCreate error\n");
758 }
759 return ca;
760 }
761 }
762
763 OSStatus addTrustedSecCert(
764 SSLContextRef ctx,
765 SecCertificateRef secCert,
766 CSSM_BOOL replaceAnchors)
767 {
768 OSStatus ortn;
769 CFMutableArrayRef array;
770
771 if(secCert == NULL) {
772 printf("***addTrustedSecCert screwup\n");
773 return paramErr;
774 }
775 array = CFArrayCreateMutable(kCFAllocatorDefault,
776 (CFIndex)1, &kCFTypeArrayCallBacks);
777 if(array == NULL) {
778 return memFullErr;
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 OSStatus sslReadAnchor(
790 const char *anchorFile,
791 SecCertificateRef *certRef)
792 {
793 OSStatus ortn;
794 SecCertificateRef secCert;
795 unsigned char *certData;
796 unsigned certLen;
797 CSSM_DATA cert;
798 int rtn;
799
800 rtn = cspReadFile(anchorFile, &certData, &certLen);
801 if(rtn) {
802 printf("cspReadFile(%s) returned %d\n", anchorFile, rtn);
803 return -1;
804 }
805 cert.Data = certData;
806 cert.Length = certLen;
807 ortn = SecCertificateCreateFromData(&cert,
808 CSSM_CERT_X_509v3,
809 CSSM_CERT_ENCODING_DER,
810 &secCert);
811 free(certData);
812 if(ortn) {
813 printf("***SecCertificateCreateFromData returned %d\n", (int)ortn);
814 return ortn;
815 }
816 *certRef = secCert;
817 return noErr;
818 }
819
820 OSStatus sslAddTrustedRoot(
821 SSLContextRef ctx,
822 const char *anchorFile,
823 CSSM_BOOL replaceAnchors)
824 {
825 OSStatus ortn;
826 SecCertificateRef secCert;
827
828 ortn = sslReadAnchor(anchorFile, &secCert);
829 if(ortn) {
830 printf("***Error (%ld) reading %s. SSLSetTrustedRoots skipped.\n",
831 (long)ortn, anchorFile);
832 return ortn;
833 }
834 return addTrustedSecCert(ctx, secCert, replaceAnchors);
835 }
836
837 #if 0
838 /* Per 3537606 this is no longer necessary */
839 /*
840 * Assume incoming identity contains a root (e.g., created by
841 * certtool) and add that cert to ST's trusted anchors. This
842 * enables ST's verify of the incoming chain to succeed without
843 * a kludgy "AllowAnyRoot" specification.
844 */
845 OSStatus addIdentityAsTrustedRoot(
846 SSLContextRef ctx,
847 CFArrayRef identArray)
848 {
849 CFIndex numItems = CFArrayGetCount(identArray);
850 if(numItems == 0) {
851 printf("***addIdentityAsTrustedRoot: empty identArray\n");
852 return paramErr;
853 }
854
855 /* Root should be the last item - could be identity, could be cert */
856 CFTypeRef theItem = CFArrayGetValueAtIndex(identArray, numItems - 1);
857 if(CFGetTypeID(theItem) == SecIdentityGetTypeID()) {
858 /* identity */
859 SecCertificateRef certRef;
860 OSStatus ortn = SecIdentityCopyCertificate(
861 (SecIdentityRef)theItem, &certRef);
862 if(ortn) {
863 cssmPerror("SecIdentityCopyCertificate", ortn);
864 printf("***Error gettting cert from identity\n");
865 return ortn;
866 }
867 ortn = addTrustedSecCert(ctx, certRef, CSSM_FALSE);
868 CFRelease(certRef);
869 return ortn;
870 }
871 else if(CFGetTypeID(theItem) == SecCertificateGetTypeID()) {
872 /* certificate */
873 return addTrustedSecCert(ctx, (SecCertificateRef)theItem, CSSM_FALSE);
874 }
875 else {
876 printf("***Bogus item in identity array\n");
877 return paramErr;
878 }
879 }
880 #else
881 OSStatus addIdentityAsTrustedRoot(
882 SSLContextRef ctx,
883 CFArrayRef identArray)
884 {
885 return noErr;
886 }
887 #endif
888
889 /*
890 * Lists of SSLCipherSuites used in sslSetCipherRestrictions. Note that the
891 * SecureTransport library does not implement all of these; we only specify
892 * the ones it claims to support.
893 */
894 const SSLCipherSuite suites40[] = {
895 SSL_RSA_EXPORT_WITH_RC4_40_MD5,
896 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
897 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
898 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
899 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
900 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
901 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
902 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
903 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
904 SSL_NO_SUCH_CIPHERSUITE
905 };
906 const SSLCipherSuite suitesDES[] = {
907 SSL_RSA_WITH_DES_CBC_SHA,
908 SSL_DH_DSS_WITH_DES_CBC_SHA,
909 SSL_DH_RSA_WITH_DES_CBC_SHA,
910 SSL_DHE_DSS_WITH_DES_CBC_SHA,
911 SSL_DHE_RSA_WITH_DES_CBC_SHA,
912 SSL_DH_anon_WITH_DES_CBC_SHA,
913 SSL_RSA_WITH_DES_CBC_MD5,
914 SSL_NO_SUCH_CIPHERSUITE
915 };
916 const SSLCipherSuite suitesDES40[] = {
917 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
918 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
919 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
920 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
921 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
922 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
923 SSL_NO_SUCH_CIPHERSUITE
924 };
925 const SSLCipherSuite suites3DES[] = {
926 SSL_RSA_WITH_3DES_EDE_CBC_SHA,
927 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
928 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
929 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
930 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
931 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
932 SSL_RSA_WITH_3DES_EDE_CBC_MD5,
933 SSL_NO_SUCH_CIPHERSUITE
934 };
935 const SSLCipherSuite suitesRC4[] = {
936 SSL_RSA_WITH_RC4_128_MD5,
937 SSL_RSA_WITH_RC4_128_SHA,
938 SSL_DH_anon_WITH_RC4_128_MD5,
939 SSL_NO_SUCH_CIPHERSUITE
940 };
941 const SSLCipherSuite suitesRC4_40[] = {
942 SSL_RSA_EXPORT_WITH_RC4_40_MD5,
943 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
944 SSL_NO_SUCH_CIPHERSUITE
945 };
946 const SSLCipherSuite suitesRC2[] = {
947 SSL_RSA_WITH_RC2_CBC_MD5,
948 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
949 SSL_NO_SUCH_CIPHERSUITE
950 };
951 const SSLCipherSuite suitesAES128[] = {
952 TLS_RSA_WITH_AES_128_CBC_SHA,
953 TLS_DH_DSS_WITH_AES_128_CBC_SHA,
954 TLS_DH_RSA_WITH_AES_128_CBC_SHA,
955 TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
956 TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
957 TLS_DH_anon_WITH_AES_128_CBC_SHA
958 };
959 const SSLCipherSuite suitesAES256[] = {
960 TLS_RSA_WITH_AES_256_CBC_SHA,
961 TLS_DH_DSS_WITH_AES_256_CBC_SHA,
962 TLS_DH_RSA_WITH_AES_256_CBC_SHA,
963 TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
964 TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
965 TLS_DH_anon_WITH_AES_256_CBC_SHA
966 };
967 const SSLCipherSuite suitesDH[] = {
968 SSL_DH_DSS_WITH_DES_CBC_SHA,
969 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
970 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
971 SSL_DH_RSA_WITH_DES_CBC_SHA,
972 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
973 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
974 SSL_DHE_DSS_WITH_DES_CBC_SHA,
975 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
976 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
977 SSL_DHE_RSA_WITH_DES_CBC_SHA,
978 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
979 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
980 SSL_DH_anon_WITH_RC4_128_MD5,
981 SSL_DH_anon_WITH_DES_CBC_SHA,
982 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
983 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
984 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
985 TLS_DH_DSS_WITH_AES_128_CBC_SHA,
986 TLS_DH_RSA_WITH_AES_128_CBC_SHA,
987 TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
988 TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
989 TLS_DH_anon_WITH_AES_128_CBC_SHA,
990 TLS_DH_DSS_WITH_AES_256_CBC_SHA,
991 TLS_DH_RSA_WITH_AES_256_CBC_SHA,
992 TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
993 TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
994 TLS_DH_anon_WITH_AES_256_CBC_SHA,
995 SSL_NO_SUCH_CIPHERSUITE
996 };
997 const SSLCipherSuite suitesDHAnon[] = {
998 SSL_DH_anon_WITH_RC4_128_MD5,
999 SSL_DH_anon_WITH_DES_CBC_SHA,
1000 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
1001 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
1002 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
1003 TLS_DH_anon_WITH_AES_128_CBC_SHA,
1004 TLS_DH_anon_WITH_AES_256_CBC_SHA,
1005 SSL_NO_SUCH_CIPHERSUITE
1006 };
1007 const SSLCipherSuite suitesDH_RSA[] = {
1008 SSL_DH_RSA_WITH_DES_CBC_SHA,
1009 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
1010 SSL_DHE_RSA_WITH_DES_CBC_SHA,
1011 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
1012 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
1013 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
1014 TLS_DH_RSA_WITH_AES_128_CBC_SHA,
1015 TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
1016 TLS_DH_RSA_WITH_AES_256_CBC_SHA,
1017 TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
1018 SSL_NO_SUCH_CIPHERSUITE
1019 };
1020 const SSLCipherSuite suitesDH_DSS[] = {
1021 SSL_DH_DSS_WITH_DES_CBC_SHA,
1022 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
1023 SSL_DHE_DSS_WITH_DES_CBC_SHA,
1024 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
1025 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
1026 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
1027 TLS_DH_DSS_WITH_AES_128_CBC_SHA,
1028 TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
1029 TLS_DH_DSS_WITH_AES_256_CBC_SHA,
1030 TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
1031 SSL_NO_SUCH_CIPHERSUITE
1032 };
1033 const SSLCipherSuite suites_SHA1[] = {
1034 SSL_RSA_WITH_RC4_128_SHA,
1035 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
1036 SSL_RSA_WITH_IDEA_CBC_SHA,
1037 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
1038 SSL_RSA_WITH_DES_CBC_SHA,
1039 SSL_RSA_WITH_3DES_EDE_CBC_SHA,
1040 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
1041 SSL_DH_DSS_WITH_DES_CBC_SHA,
1042 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
1043 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
1044 SSL_DH_RSA_WITH_DES_CBC_SHA,
1045 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
1046 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
1047 SSL_DHE_DSS_WITH_DES_CBC_SHA,
1048 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
1049 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
1050 SSL_DHE_RSA_WITH_DES_CBC_SHA,
1051 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
1052 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
1053 SSL_DH_anon_WITH_DES_CBC_SHA,
1054 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
1055 SSL_FORTEZZA_DMS_WITH_NULL_SHA,
1056 SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,
1057 TLS_RSA_WITH_AES_128_CBC_SHA,
1058 TLS_DH_DSS_WITH_AES_128_CBC_SHA,
1059 TLS_DH_RSA_WITH_AES_128_CBC_SHA,
1060 TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
1061 TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
1062 TLS_DH_anon_WITH_AES_128_CBC_SHA,
1063 TLS_RSA_WITH_AES_256_CBC_SHA,
1064 TLS_DH_DSS_WITH_AES_256_CBC_SHA,
1065 TLS_DH_RSA_WITH_AES_256_CBC_SHA,
1066 TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
1067 TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
1068 TLS_DH_anon_WITH_AES_256_CBC_SHA,
1069 SSL_NO_SUCH_CIPHERSUITE
1070 };
1071 const SSLCipherSuite suites_MD5[] = {
1072 SSL_RSA_EXPORT_WITH_RC4_40_MD5,
1073 SSL_RSA_WITH_RC4_128_MD5,
1074 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
1075 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
1076 SSL_DH_anon_WITH_RC4_128_MD5,
1077 SSL_NO_SUCH_CIPHERSUITE
1078 };
1079 const SSLCipherSuite suites_NULL[] = {
1080 SSL_RSA_WITH_NULL_MD5,
1081 SSL_NO_SUCH_CIPHERSUITE
1082 };
1083
1084 const SSLCipherSuite suites_ECDHE[] = {
1085 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
1086 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
1087 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
1088 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
1089 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
1090 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
1091 TLS_ECDHE_RSA_WITH_RC4_128_SHA,
1092 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
1093 SSL_NO_SUCH_CIPHERSUITE
1094 };
1095
1096 const SSLCipherSuite suites_ECDH[] = {
1097 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
1098 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
1099 TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
1100 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
1101 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
1102 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
1103 TLS_ECDH_RSA_WITH_RC4_128_SHA,
1104 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
1105 SSL_NO_SUCH_CIPHERSUITE
1106 };
1107
1108
1109 /*
1110 * Given an SSLContextRef and an array of SSLCipherSuites, terminated by
1111 * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library
1112 * supports and do a SSLSetEnabledCiphers() specifying those.
1113 */
1114 OSStatus sslSetEnabledCiphers(
1115 SSLContextRef ctx,
1116 const SSLCipherSuite *ciphers)
1117 {
1118 size_t numSupported;
1119 OSStatus ortn;
1120 SSLCipherSuite *supported = NULL;
1121 SSLCipherSuite *enabled = NULL;
1122 unsigned enabledDex = 0; // index into enabled
1123 unsigned supportedDex = 0; // index into supported
1124 unsigned inDex = 0; // index into ciphers
1125
1126 /* first get all the supported ciphers */
1127 ortn = SSLGetNumberSupportedCiphers(ctx, &numSupported);
1128 if(ortn) {
1129 printSslErrStr("SSLGetNumberSupportedCiphers", ortn);
1130 return ortn;
1131 }
1132 supported = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1133 ortn = SSLGetSupportedCiphers(ctx, supported, &numSupported);
1134 if(ortn) {
1135 printSslErrStr("SSLGetSupportedCiphers", ortn);
1136 return ortn;
1137 }
1138
1139 /*
1140 * Malloc an array we'll use for SSLGetEnabledCiphers - this will be
1141 * bigger than the number of suites we actually specify
1142 */
1143 enabled = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1144
1145 /*
1146 * For each valid suite in ciphers, see if it's in the list of
1147 * supported ciphers. If it is, add it to the list of ciphers to be
1148 * enabled.
1149 */
1150 for(inDex=0; ciphers[inDex] != SSL_NO_SUCH_CIPHERSUITE; inDex++) {
1151 for(supportedDex=0; supportedDex<numSupported; supportedDex++) {
1152 if(ciphers[inDex] == supported[supportedDex]) {
1153 enabled[enabledDex++] = ciphers[inDex];
1154 break;
1155 }
1156 }
1157 }
1158
1159 /* send it on down. */
1160 ortn = SSLSetEnabledCiphers(ctx, enabled, enabledDex);
1161 if(ortn) {
1162 printSslErrStr("SSLSetEnabledCiphers", ortn);
1163 }
1164 free(enabled);
1165 free(supported);
1166 return ortn;
1167 }
1168
1169 /*
1170 * Specify a restricted set of cipherspecs.
1171 */
1172 OSStatus sslSetCipherRestrictions(
1173 SSLContextRef ctx,
1174 char cipherRestrict)
1175 {
1176 OSStatus ortn;
1177
1178 if(cipherRestrict == '\0') {
1179 return noErr; // actually should not have been called
1180 }
1181 switch(cipherRestrict) {
1182 case 'e':
1183 ortn = sslSetEnabledCiphers(ctx, suites40);
1184 break;
1185 case 'd':
1186 ortn = sslSetEnabledCiphers(ctx, suitesDES);
1187 break;
1188 case 'D':
1189 ortn = sslSetEnabledCiphers(ctx, suitesDES40);
1190 break;
1191 case '3':
1192 ortn = sslSetEnabledCiphers(ctx, suites3DES);
1193 break;
1194 case '4':
1195 ortn = sslSetEnabledCiphers(ctx, suitesRC4);
1196 break;
1197 case '$':
1198 ortn = sslSetEnabledCiphers(ctx, suitesRC4_40);
1199 break;
1200 case '2':
1201 ortn = sslSetEnabledCiphers(ctx, suitesRC2);
1202 break;
1203 case 'a':
1204 ortn = sslSetEnabledCiphers(ctx, suitesAES128);
1205 break;
1206 case 'A':
1207 ortn = sslSetEnabledCiphers(ctx, suitesAES256);
1208 break;
1209 case 'h':
1210 ortn = sslSetEnabledCiphers(ctx, suitesDH);
1211 break;
1212 case 'H':
1213 ortn = sslSetEnabledCiphers(ctx, suitesDHAnon);
1214 break;
1215 case 'r':
1216 ortn = sslSetEnabledCiphers(ctx, suitesDH_RSA);
1217 break;
1218 case 's':
1219 ortn = sslSetEnabledCiphers(ctx, suitesDH_DSS);
1220 break;
1221 case 'n':
1222 ortn = sslSetEnabledCiphers(ctx, suites_NULL);
1223 break;
1224 case 'E':
1225 ortn = sslSetEnabledCiphers(ctx, suites_ECDHE);
1226 break;
1227 case 'F':
1228 ortn = sslSetEnabledCiphers(ctx, suites_ECDH);
1229 break;
1230 default:
1231 printf("***bad cipherSpec***\n");
1232 exit(1);
1233 }
1234 return ortn;
1235 }
1236
1237 int sslVerifyClientCertState(
1238 const char *whichSide, // "client" or "server"
1239 SSLClientCertificateState expectState,
1240 SSLClientCertificateState gotState)
1241 {
1242 if(expectState == SSL_CLIENT_CERT_IGNORE) {
1243 /* app says "don't bother checking" */
1244 return 0;
1245 }
1246 if(expectState == gotState) {
1247 return 0;
1248 }
1249 printf("***%s: Expected clientCertState %s; got %s\n", whichSide,
1250 sslGetClientCertStateString(expectState),
1251 sslGetClientCertStateString(gotState));
1252 return 1;
1253 }
1254
1255 int sslVerifyRtn(
1256 const char *whichSide, // "client" or "server"
1257 OSStatus expectRtn,
1258 OSStatus gotRtn)
1259 {
1260 if(expectRtn == gotRtn) {
1261 return 0;
1262 }
1263 printf("***%s: Expected return %s; got %s\n", whichSide,
1264 sslGetSSLErrString(expectRtn),
1265 sslGetSSLErrString(gotRtn));
1266 return 1;
1267 }
1268
1269 int sslVerifyProtVers(
1270 const char *whichSide, // "client" or "server"
1271 SSLProtocol expectProt,
1272 SSLProtocol gotProt)
1273 {
1274 if(expectProt == SSL_PROTOCOL_IGNORE) {
1275 /* app says "don't bopther checking" */
1276 return 0;
1277 }
1278 if(expectProt == gotProt) {
1279 return 0;
1280 }
1281 printf("***%s: Expected return %s; got %s\n", whichSide,
1282 sslGetProtocolVersionString(expectProt),
1283 sslGetProtocolVersionString(gotProt));
1284 return 1;
1285 }
1286
1287 int sslVerifyCipher(
1288 const char *whichSide, // "client" or "server"
1289 SSLCipherSuite expectCipher,
1290 SSLCipherSuite gotCipher)
1291 {
1292 if(expectCipher == SSL_CIPHER_IGNORE) {
1293 /* app says "don't bopther checking" */
1294 return 0;
1295 }
1296 if(expectCipher == gotCipher) {
1297 return 0;
1298 }
1299 printf("***%s: Expected return %s; got %s\n", whichSide,
1300 sslGetCipherSuiteString(expectCipher),
1301 sslGetCipherSuiteString(gotCipher));
1302 return 1;
1303 }
1304
1305
1306 OSStatus sslSetProtocols(
1307 SSLContextRef ctx,
1308 const char *acceptedProts,
1309 SSLProtocol tryVersion) // only used if acceptedProts NULL
1310 {
1311 OSStatus ortn;
1312
1313 if(acceptedProts) {
1314 ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false);
1315 if(ortn) {
1316 printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn);
1317 return ortn;
1318 }
1319 for(const char *cp = acceptedProts; *cp; cp++) {
1320 SSLProtocol prot;
1321 switch(*cp) {
1322 case '2':
1323 prot = kSSLProtocol2;
1324 break;
1325 case '3':
1326 prot = kSSLProtocol3;
1327 break;
1328 case 't':
1329 prot = kTLSProtocol1;
1330 break;
1331 default:
1332 printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts);
1333 exit(1);
1334 }
1335 ortn = SSLSetProtocolVersionEnabled(ctx, prot, true);
1336 if(ortn) {
1337 printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
1338 return ortn;
1339 }
1340 }
1341 }
1342 else {
1343 ortn = SSLSetProtocolVersion(ctx, tryVersion);
1344 if(ortn) {
1345 printSslErrStr("SSLSetProtocolVersion", ortn);
1346 return ortn;
1347 }
1348 }
1349 return noErr;
1350 }
1351
1352 void sslShowResult(
1353 const char *whichSide, // "client" or "server"
1354 SslAppTestParams *params)
1355 {
1356 printf("%s status:\n", whichSide);
1357 if(params->acceptedProts) {
1358 printf(" Allowed SSL versions : %s\n", params->acceptedProts);
1359 }
1360 else {
1361 printf(" Attempted SSL version : %s\n",
1362 sslGetProtocolVersionString(params->tryVersion));
1363 }
1364 printf(" Result : %s\n", sslGetSSLErrString(params->ortn));
1365 printf(" Negotiated SSL version : %s\n",
1366 sslGetProtocolVersionString(params->negVersion));
1367 printf(" Negotiated CipherSuite : %s\n",
1368 sslGetCipherSuiteString(params->negCipher));
1369 if(params->certState != kSSLClientCertNone) {
1370 printf(" Client Cert State : %s\n",
1371 sslGetClientCertStateString(params->certState));
1372 }
1373 }
1374
1375 /* print a '.' every few seconds to keep UI alive while connecting */
1376 static CFAbsoluteTime lastTime = (CFAbsoluteTime)0.0;
1377 #define TIME_INTERVAL 3.0
1378
1379 void sslOutputDot()
1380 {
1381 CFAbsoluteTime thisTime = CFAbsoluteTimeGetCurrent();
1382
1383 if(lastTime == 0.0) {
1384 /* avoid printing first time thru */
1385 lastTime = thisTime;
1386 return;
1387 }
1388 if((thisTime - lastTime) >= TIME_INTERVAL) {
1389 printf("."); fflush(stdout);
1390 lastTime = thisTime;
1391 }
1392 }
1393
1394 /* main server pthread body */
1395 static void *sslServerThread(void *arg)
1396 {
1397 SslAppTestParams *testParams = (SslAppTestParams *)arg;
1398 OSStatus status;
1399
1400 status = sslAppServe(testParams);
1401 pthread_exit((void*)status);
1402 /* NOT REACHED */
1403 return (void *)status;
1404 }
1405
1406 /*
1407 * Run one session, with the server in a separate thread.
1408 * On entry, serverParams->port is the port we attempt to run on;
1409 * the server thread may overwrite that with a different port if it's
1410 * unable to open the port we specify. Whatever is left in
1411 * serverParams->port is what's used for the client side.
1412 */
1413 #define CLIENT_WAIT_SECONDS 1
1414 int sslRunSession(
1415 SslAppTestParams*serverParams,
1416 SslAppTestParams *clientParams,
1417 const char *testDesc)
1418 {
1419 pthread_t serverPthread;
1420 OSStatus clientRtn;
1421 void *serverRtn;
1422
1423 if(testDesc && !clientParams->quiet) {
1424 printf("===== %s =====\n", testDesc);
1425 }
1426
1427 /*
1428 * Workaround for Radar 4619502: resolve references to Security.framework
1429 * here, in main thread, before we fork off the server thread.
1430 */
1431 SecKeychainRef defaultKc = NULL;
1432 SecKeychainCopyDefault(&defaultKc);
1433 /* end workaround */
1434
1435 if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) {
1436 printf("***Error initializing mutex; aborting.\n");
1437 return -1;
1438 }
1439 if(pthread_cond_init(&serverParams->pthreadCond, NULL)) {
1440 printf("***Error initializing pthreadCond; aborting.\n");
1441 return -1;
1442 }
1443 serverParams->serverReady = false; // server sets true
1444
1445 int result = pthread_create(&serverPthread, NULL,
1446 sslServerThread, serverParams);
1447 if(result) {
1448 printf("***Error starting up server thread; aborting.\n");
1449 return result;
1450 }
1451
1452 /* wait for server to set up a socket we can connect to */
1453 if(pthread_mutex_lock(&serverParams->pthreadMutex)) {
1454 printf("***Error acquiring server lock; aborting.\n");
1455 return -1;
1456 }
1457 while(!serverParams->serverReady) {
1458 if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) {
1459 printf("***Error waiting server thread; aborting.\n");
1460 return -1;
1461 }
1462 }
1463 pthread_mutex_unlock(&serverParams->pthreadMutex);
1464 pthread_cond_destroy(&serverParams->pthreadCond);
1465 pthread_mutex_destroy(&serverParams->pthreadMutex);
1466
1467 clientParams->port = serverParams->port;
1468 clientRtn = sslAppClient(clientParams);
1469 /* server doesn't shut down its socket until it sees this */
1470 serverParams->clientDone = 1;
1471 result = pthread_join(serverPthread, &serverRtn);
1472 if(result) {
1473 printf("***pthread_join returned %d, aborting\n", result);
1474 return result;
1475 }
1476
1477 if(serverParams->verbose) {
1478 sslShowResult("server", serverParams);
1479 }
1480 if(clientParams->verbose) {
1481 sslShowResult("client", clientParams);
1482 }
1483
1484 /* verify results */
1485 int ourRtn = 0;
1486 ourRtn += sslVerifyRtn("server", serverParams->expectRtn, serverParams->ortn);
1487 ourRtn += sslVerifyRtn("client", clientParams->expectRtn, clientParams->ortn);
1488 ourRtn += sslVerifyProtVers("server", serverParams->expectVersion,
1489 serverParams->negVersion);
1490 ourRtn += sslVerifyProtVers("client", clientParams->expectVersion,
1491 clientParams->negVersion);
1492 ourRtn += sslVerifyClientCertState("server", serverParams->expectCertState,
1493 serverParams->certState);
1494 ourRtn += sslVerifyClientCertState("client", clientParams->expectCertState,
1495 clientParams->certState);
1496 if(serverParams->ortn == noErr) {
1497 ourRtn += sslVerifyCipher("server", serverParams->expectCipher,
1498 serverParams->negCipher);
1499 }
1500 if(clientParams->ortn == noErr) {
1501 ourRtn += sslVerifyCipher("client", clientParams->expectCipher,
1502 clientParams->negCipher);
1503 }
1504
1505 if(defaultKc) {
1506 /* for workaround for Radar 4619502 */
1507 CFRelease(defaultKc);
1508 }
1509 return ourRtn;
1510 }
1511
1512 /*
1513 * Add all of the roots in a given KC to SSL ctx's trusted anchors.
1514 */
1515 OSStatus sslAddTrustedRoots(
1516 SSLContextRef ctx,
1517 SecKeychainRef keychain,
1518 bool *foundOne) // RETURNED, true if we found
1519 // at least one root cert
1520 {
1521 OSStatus ortn;
1522 SecCertificateRef secCert;
1523 SecKeychainSearchRef srch;
1524
1525 *foundOne = false;
1526 ortn = SecKeychainSearchCreateFromAttributes(keychain,
1527 kSecCertificateItemClass,
1528 NULL, // any attrs
1529 &srch);
1530 if(ortn) {
1531 printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn);
1532 return ortn;
1533 }
1534
1535 /*
1536 * Only use root certs. Not an error if we don't find any.
1537 */
1538 do {
1539 ortn = SecKeychainSearchCopyNext(srch,
1540 (SecKeychainItemRef *)&secCert);
1541 if(ortn) {
1542 break;
1543 }
1544
1545 /* see if it's a root */
1546 if(!isCertRefRoot(secCert)) {
1547 continue;
1548 }
1549
1550 /* Tell Secure Transport to trust this one. */
1551 ortn = addTrustedSecCert(ctx, secCert, false);
1552 if(ortn) {
1553 /* fatal */
1554 printSslErrStr("addTrustedSecCert", ortn);
1555 return ortn;
1556 }
1557 CFRelease(secCert);
1558 *foundOne = true;
1559 } while(ortn == noErr);
1560 CFRelease(srch);
1561 return noErr;
1562 }
1563
1564 /*
1565 * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename.
1566 */
1567 OSStatus sslIdentityPicker(
1568 SecKeychainRef kcRef, // NULL means use default list
1569 const char *trustedAnchor, // optional additional trusted anchor
1570 bool includeRoot, // true --> root is appended to outArray
1571 // false --> root not included
1572 const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL
1573 CFArrayRef *outArray) // created and RETURNED
1574 {
1575 SecCertificateRef trustedCert = NULL;
1576 OSStatus ortn;
1577
1578 if(trustedAnchor) {
1579 ortn = sslReadAnchor(trustedAnchor, &trustedCert);
1580 if(ortn) {
1581 printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n",
1582 trustedAnchor);
1583 trustedCert = NULL;
1584 }
1585 }
1586 ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, vfyPolicy, outArray);
1587 if(trustedCert) {
1588 CFRelease(trustedCert);
1589 }
1590 return ortn;
1591 }
1592
1593 /*
1594 * Given a keychain name, convert it into a full path using the "SSL regression
1595 * test suite algorithm". The Sec layer by default locates root root's keychains
1596 * in different places depending on whether we're actually logged in as root
1597 * or running via e.g. cron, so we force the location of root keychains to
1598 * a hard-coded path. User keychain names we leave alone.
1599 * This has to be kept in sync with the sslKcSetup script fragment in
1600 * sslScripts.
1601 */
1602 void sslKeychainPath(
1603 const char *kcName,
1604 char *kcPath) // allocd by caller, MAXPATHLEN
1605 {
1606 if(kcName[0] == '\0') {
1607 kcPath[0] = '\0';
1608 }
1609 else if(geteuid() == 0) {
1610 /* root */
1611 const char *buildDir = getenv("LOCAL_BUILD_DIR");
1612 if(buildDir == NULL) {
1613 buildDir = "";
1614 }
1615 sprintf(kcPath, "%s/Library/Keychains/%s", buildDir, kcName);
1616 }
1617 else {
1618 /* user, leave alone */
1619 strcpy(kcPath, kcName);
1620 }
1621 }
1622
1623 /* Verify presence of required file. Returns nonzero if not found. */
1624 int sslCheckFile(const char *path)
1625 {
1626 struct stat sb;
1627
1628 if(stat(path, &sb)) {
1629 printf("***Can't find file %s.\n", path);
1630 printf(" Try running in the build directory, perhaps after running the\n"
1631 " makeLocalCert script.\n");
1632 return 1;
1633 }
1634 return 0;
1635 }
1636
1637 /* Stringify a SSL_ECDSA_NamedCurve */
1638 extern const char *sslCurveString(
1639 SSL_ECDSA_NamedCurve namedCurve)
1640 {
1641 static char unk[100];
1642
1643 switch(namedCurve) {
1644 case SSL_Curve_None: return "Curve_None";
1645 case SSL_Curve_secp256r1: return "secp256r1";
1646 case SSL_Curve_secp384r1: return "secp384r1";
1647 case SSL_Curve_secp521r1: return "secp521r1";
1648 default:
1649 sprintf(unk, "Unknown <%d>", (int)namedCurve);
1650 return unk;
1651 }
1652 }
1653