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 26const 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 */ 136const 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 */ 166const 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 308void printSslErrStr( 309 const char *op, 310 OSStatus err) 311{ 312 printf("*** %s: %s\n", op, sslGetSSLErrString(err)); 313} 314 315const 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 */ 343CFArrayRef 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 436errOut: 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 */ 457static 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 } 500errOut: 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 */ 513OSStatus 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 } 664errOut: 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 */ 687CFArrayRef 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 763OSStatus 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 790OSStatus 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 819OSStatus 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 */ 848OSStatus 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 884OSStatus 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 */ 897const 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}; 909const 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}; 919const 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}; 928const 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}; 938const 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}; 944const 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}; 949const SSLCipherSuite suitesRC2[] = { 950 SSL_RSA_WITH_RC2_CBC_MD5, 951 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, 952 SSL_NO_SUCH_CIPHERSUITE 953}; 954const 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}; 963const 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}; 972const 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}; 1002const 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}; 1012const 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}; 1025const 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}; 1038const 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}; 1076const 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 */ 1091OSStatus 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 */ 1149OSStatus 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 1206int 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 1224int 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 1238int 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 1256int 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 1275OSStatus 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 1325void 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 */ 1350static time_t lastTime = (time_t)0; 1351#define TIME_INTERVAL 3 1352 1353void 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 */ 1365static 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 1384int 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 1469static 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 */ 1484OSStatus 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 */ 1536OSStatus 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 */ 1568void 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. */ 1586int 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 */ 1602extern 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} 1617