/* Test basic add delete update copy matching stuff. */ static void tests(void) { SecTrustRef trust; SecCertificateRef cert0, cert1; isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), NULL, "create cert0"); isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), NULL, "create cert1"); const void *v_certs[] = { cert0, cert1 }; SecPolicyRef policy = SecPolicyCreateSSL(false, CFSTR("store.apple.com")); CFArrayRef certs = CFArrayCreate(NULL, v_certs, array_size(v_certs), NULL); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); /* Jan 1st 2006. */ CFDateRef date = CFDateCreate(NULL, 157680000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); SecTrustResultType trustResult; ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); CFDataRef exceptions; ok(exceptions = SecTrustCopyExceptions(trust), "create an exceptions"); ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); CFReleaseSafe(trust); CFReleaseSafe(policy); policy = SecPolicyCreateSSL(false, CFSTR("badstore.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust with hostname mismatch"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); ok(SecTrustSetExceptions(trust, exceptions), "set old exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); CFReleaseSafe(exceptions); ok(exceptions = SecTrustCopyExceptions(trust), "create a new exceptions"); ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); CFReleaseSafe(trust); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); CFArrayRef anchors = CFArrayCreate(kCFAllocatorDefault, NULL, 0, &kCFTypeArrayCallBacks); ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set empty anchor list"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); ok_status(SecTrustSetAnchorCertificatesOnly(trust, false), "trust passed in anchors and system anchors"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is now kSecTrustResultProceed"); ok_status(SecTrustSetAnchorCertificatesOnly(trust, true), "only trust passed in anchors (default)"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure again"); CFReleaseSafe(exceptions); ok(exceptions = SecTrustCopyExceptions(trust), "create a new exceptions"); ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); CFReleaseSafe(date); date = CFDateCreate(NULL, 667680000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set date to far future so certs are expired"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); CFReleaseSafe(anchors); CFReleaseSafe(exceptions); CFReleaseSafe(trust); CFReleaseSafe(policy); CFReleaseSafe(certs); CFReleaseSafe(cert0); CFReleaseSafe(cert1); CFReleaseSafe(date); }
OSStatus sslCreateSecTrust( SSLContext *ctx, SecTrustRef *pTrust) /* RETURNED */ { OSStatus status = errSecAllocate; SecTrustRef trust = NULL; require_noerr(status = tls_helper_create_peer_trust(ctx->hdsk, ctx->protocolSide==kSSLServerSide, &trust), errOut); /* If we have trustedAnchors we set them here. */ if (trust && ctx->trustedCerts) { require_noerr(status = SecTrustSetAnchorCertificates(trust, ctx->trustedCerts), errOut); require_noerr(status = SecTrustSetAnchorCertificatesOnly(trust, ctx->trustedCertsOnly), errOut); } status = errSecSuccess; errOut: if(status != noErr) { CFReleaseSafe(trust); *pTrust = NULL; } else { *pTrust = trust; } return status; }
OSStatus sslCreateSecTrust( SSLContext *ctx, CFArrayRef certChain, bool arePeerCerts, SecTrustRef *pTrust) /* RETURNED */ { OSStatus status = memFullErr; CFStringRef peerDomainName = NULL; CFTypeRef policies = NULL; SecTrustRef trust = NULL; if (CFArrayGetCount(certChain) == 0) { status = errSSLBadCert; goto errOut; } if (arePeerCerts) { if (ctx->peerDomainNameLen && ctx->peerDomainName) { CFIndex len = ctx->peerDomainNameLen; if (ctx->peerDomainName[len - 1] == 0) { len--; //secwarning("peerDomainName is zero terminated!"); } /* @@@ Double check that this is the correct encoding. */ require(peerDomainName = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)ctx->peerDomainName, len, kCFStringEncodingUTF8, false), errOut); } } /* If we are the client, our peer certificates must satisfy the ssl server policy. */ bool server = ctx->protocolSide == kSSLClientSide; require(policies = SecPolicyCreateSSL(server, peerDomainName), errOut); require_noerr(status = SecTrustCreateWithCertificates(certChain, policies, &trust), errOut); /* If we have trustedAnchors we set them here. */ if (ctx->trustedCerts) { require_noerr(status = SecTrustSetAnchorCertificates(trust, ctx->trustedCerts), errOut); require_noerr(status = SecTrustSetAnchorCertificatesOnly(trust, ctx->trustedCertsOnly), errOut); } status = noErr; errOut: CFReleaseSafe(peerDomainName); CFReleaseSafe(policies); *pTrust = trust; return status; }
bool Connection::readHandshake() { log_trace("Connection::readHandshake"); std::streambuf* sb = _ios->rdbuf(); if( ! sb) return true; _maxImport = sb->in_avail(); _wantRead = false; _isReading = true; OSStatus status = SSLHandshake(_context); _isReading = false; log_debug("SSLHandshake returns " << status); if( status == noErr ) { log_debug("SSL handshake completed"); _connected = true; return false; } #ifdef PT_IOS if(status == errSSLPeerAuthCompleted) #else if(status == errSSLServerAuthCompleted) #endif { log_debug("authenticating peer"); if( _ctx->verifyMode() != NoVerify ) { log_debug("evaluating trust"); SecTrustRef trust = NULL; SSLCopyPeerTrust(_context, &trust); CFArrayRef caArr = _ctx->impl()->caCertificates(); SecTrustSetAnchorCertificates(trust, caArr); SecTrustSetAnchorCertificatesOnly(trust, true); SecTrustResultType result; OSStatus evalErr = SecTrustEvaluate(trust, &result); if(evalErr) throw HandshakeFailed("SSL handshake failed"); CFIndex count = SecTrustGetCertificateCount(trust); log_debug("SecTrustEvaluate: " << result << " certs: " << count); if(trust) CFRelease(trust); // if peer presented no certificate, SecTrustGetCertificateCount // should return 0. If we require one because AlwaysVerify is // set, the handshake is considered to be failed if(_ctx->verifyMode() == AlwaysVerify && count == 0) throw HandshakeFailed("SSL handshake failed"); if( (result != kSecTrustResultProceed) && (result != kSecTrustResultUnspecified) ) throw HandshakeFailed("SSL handshake failed"); log_debug("authentication successful"); } return readHandshake(); } if( status != errSSLWouldBlock ) { throw HandshakeFailed("SSL handshake failed"); } return _wantRead; }
/* Test basic add delete update copy matching stuff. */ static void tests(void) { SecTrustRef trust; SecCertificateRef cert0, cert1; isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), NULL, "create cert0"); isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), NULL, "create cert1"); const void *v_certs[] = { cert0, cert1 }; SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); CFArrayRef certs = CFArrayCreate(NULL, v_certs, array_size(v_certs), NULL); /* SecTrustCreateWithCertificates using single cert. */ ok_status(SecTrustCreateWithCertificates(cert0, policy, &trust), "create trust with single cert0"); is(SecTrustGetCertificateCount(trust), 1, "cert count is 1"); is(SecTrustGetCertificateAtIndex(trust, 0), cert0, "cert 0 is leaf"); CFReleaseNull(trust); /* SecTrustCreateWithCertificates failures. */ is_status(SecTrustCreateWithCertificates(kCFBooleanTrue, policy, &trust), errSecParam, "create trust with boolean instead of cert"); is_status(SecTrustCreateWithCertificates(cert0, kCFBooleanTrue, &trust), errSecParam, "create trust with boolean instead of policy"); /* SecTrustCreateWithCertificates using array of certs. */ ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); /* NOTE: prior to <rdar://11810677 SecTrustGetCertificateCount would return 1 at this point. * Now, however, we do an implicit SecTrustEvaluate to build the chain if it has not yet been * evaluated, so we now expect the full chain length. */ is(SecTrustGetCertificateCount(trust), 3, "cert count is 3"); is(SecTrustGetCertificateAtIndex(trust, 0), cert0, "cert 0 is leaf"); /* Jan 1st 2006. */ CFDateRef date = CFDateCreate(NULL, 157680000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); is(SecTrustGetVerifyTime(trust), 157680000.0, "get date"); SecTrustResultType trustResult; SKIP: { #ifdef NO_SERVER skip("Can't fail to connect to securityd in NO_SERVER mode", 4, false); #endif // Test Restore OS environment SecServerSetMachServiceName("com.apple.security.doesn't-exist"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust without securityd running"); is_status(trustResult, kSecTrustResultInvalid, "trustResult is kSecTrustResultInvalid"); is(SecTrustGetCertificateCount(trust), 1, "cert count is 1 without securityd running"); SecKeyRef pubKey = NULL; ok(pubKey = SecTrustCopyPublicKey(trust), "copy public key without securityd running"); CFReleaseNull(pubKey); SecServerSetMachServiceName(NULL); // End of Restore OS environment tests } ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trustResult is kSecTrustResultUnspecified"); is(SecTrustGetCertificateCount(trust), 3, "cert count is 3"); CFDataRef c0_serial = CFDataCreate(NULL, _c0_serial, sizeof(_c0_serial)); CFDataRef serial; ok(serial = SecCertificateCopySerialNumber(cert0), "copy cert0 serial"); ok(CFEqual(c0_serial, serial), "serial matches"); CFArrayRef anchors = CFArrayCreate(NULL, (const void **)&cert1, 1, &kCFTypeArrayCallBacks); ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); is(SecTrustGetCertificateCount(trust), 2, "cert count is 2"); CFReleaseSafe(anchors); anchors = CFArrayCreate(NULL, NULL, 0, NULL); ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set empty anchors list"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); ok_status(SecTrustSetAnchorCertificatesOnly(trust, false), "trust passed in anchors and system anchors"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); ok_status(SecTrustSetAnchorCertificatesOnly(trust, true), "only trust passed in anchors (default)"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); /* Test cert_1 intermididate from the keychain. */ CFReleaseSafe(trust); ok_status(SecTrustCreateWithCertificates(cert0, policy, &trust), "create trust with single cert0"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); // Add cert1 CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecClass, kSecClassCertificate, kSecValueRef, cert1, NULL); ok_status(SecItemAdd(query, NULL), "add cert1 to keychain"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); // Cleanup added cert1. ok_status(SecItemDelete(query), "remove cert1 from keychain"); CFReleaseSafe(query); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); is(SecTrustGetCertificateCount(trust), 3, "cert count is 3"); /* Set certs to be the xedge2 leaf. */ CFReleaseSafe(certs); const void *cert_xedge2; isnt(cert_xedge2 = SecCertificateCreateWithBytes(NULL, xedge2_certificate, sizeof(xedge2_certificate)), NULL, "create cert_xedge2"); certs = CFArrayCreate(NULL, &cert_xedge2, 1, NULL); CFReleaseSafe(trust); CFReleaseSafe(policy); CFReleaseSafe(date); bool server = true; policy = SecPolicyCreateSSL(server, CFSTR("xedge2.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ssl server xedge2.apple.com"); /* Jan 1st 2009. */ date = CFDateCreate(NULL, 252288000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); CFReleaseSafe(trust); CFReleaseSafe(policy); server = false; policy = SecPolicyCreateSSL(server, CFSTR("xedge2.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ssl client xedge2.apple.com"); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); CFReleaseSafe(trust); CFReleaseSafe(policy); server = true; policy = SecPolicyCreateIPSec(server, CFSTR("xedge2.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ip server xedge2.apple.com"); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); #if 0 /* Although this shouldn't be a valid ipsec cert, since we no longer check for ekus in the ipsec policy it is. */ is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); #else is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); #endif CFReleaseSafe(trust); CFReleaseSafe(policy); server = true; policy = SecPolicyCreateSSL(server, CFSTR("nowhere.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ssl server nowhere.com"); SecPolicyRef replacementPolicy = SecPolicyCreateSSL(server, CFSTR("xedge2.apple.com")); SecTrustSetPolicies(trust, replacementPolicy); CFReleaseSafe(replacementPolicy); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); CFReleaseSafe(trust); CFReleaseSafe(policy); server = true; policy = SecPolicyCreateSSL(server, CFSTR("nowhere.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ssl server nowhere.com"); SecPolicyRef replacementPolicy2 = SecPolicyCreateSSL(server, CFSTR("xedge2.apple.com")); CFArrayRef replacementPolicies = CFArrayCreate(kCFAllocatorDefault, (CFTypeRef*)&replacementPolicy2, 1, &kCFTypeArrayCallBacks); SecTrustSetPolicies(trust, replacementPolicies); CFReleaseSafe(replacementPolicy2); CFReleaseSafe(replacementPolicies); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); /* Test self signed ssl cert with cert itself set as anchor. */ CFReleaseSafe(trust); CFReleaseSafe(policy); CFReleaseSafe(certs); CFReleaseSafe(date); const void *garthc2; server = true; isnt(garthc2 = SecCertificateCreateWithBytes(NULL, garthc2_certificate, sizeof(garthc2_certificate)), NULL, "create garthc2"); certs = CFArrayCreate(NULL, &garthc2, 1, NULL); policy = SecPolicyCreateSSL(server, CFSTR("garthc2.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ip server garthc2.apple.com"); date = CFDateCreate(NULL, 269568000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set garthc2 trust date to Aug 2009"); ok_status(SecTrustSetAnchorCertificates(trust, certs), "set garthc2 as anchor"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate self signed cert with cert as anchor"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); CFReleaseSafe(garthc2); CFReleaseSafe(cert_xedge2); CFReleaseSafe(anchors); CFReleaseSafe(trust); CFReleaseSafe(serial); CFReleaseSafe(c0_serial); CFReleaseSafe(policy); CFReleaseSafe(certs); CFReleaseSafe(cert0); CFReleaseSafe(cert1); CFReleaseSafe(date); /* Test prt_forest_fi */ const void *prt_forest_fi; isnt(prt_forest_fi = SecCertificateCreateWithBytes(NULL, prt_forest_fi_certificate, sizeof(prt_forest_fi_certificate)), NULL, "create prt_forest_fi"); isnt(certs = CFArrayCreate(NULL, &prt_forest_fi, 1, NULL), NULL, "failed to create cert array"); policy = SecPolicyCreateSSL(false, CFSTR("owa.prt-forest.fi")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ip client owa.prt-forest.fi"); date = CFDateCreate(NULL, 391578321.0); ok_status(SecTrustSetVerifyDate(trust, date), "set owa.prt-forest.fi trust date to May 2013"); SecKeyRef pubkey = SecTrustCopyPublicKey(trust); is(pubkey, NULL, "pubkey returned"); CFReleaseSafe(certs); CFReleaseNull(prt_forest_fi); CFReleaseNull(policy); CFReleaseNull(trust); CFReleaseNull(pubkey); CFReleaseNull(date); }