#include <string.h>
#include <assert.h>
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
-#include <Security/cssm.h>
-/* these are to be replaced by Security/Security.h */
-#include <Security/SecCertificate.h>
-#include <Security/SecKeychainItem.h>
-#include <Security/SecKeychain.h>
-#include <Security/SecIdentity.h>
-#include <Security/SecIdentitySearch.h>
-#include <Security/SecKey.h>
-
-#if ST_MANAGES_TRUSTED_ROOTS
-static OSStatus
-addCertData(
- SSLContext *ctx,
- KCItemRef kcItem,
- CSSM_DATA_PTR certData,
- Boolean *goodCert); /* RETURNED */
-#endif /* ST_MANAGES_TRUSTED_ROOTS */
+#include <Security/Security.h>
/*
* Given an array of certs (as SecIdentityRefs, specified by caller
CFArrayRef certs,
SSLCertificate **destCert, /* &ctx->{localCert,encryptCert} */
CSSM_KEY_PTR *pubKey, /* &ctx->signingPubKey, etc. */
- CSSM_KEY_PTR *privKey, /* &ctx->signingPrivKey, etc. */
- CSSM_CSP_HANDLE *cspHand /* &ctx->signingKeyCsp, etc. */
- #if ST_KC_KEYS_NEED_REF
- ,
- SecKeychainRef *privKeyRef) /* &ctx->signingKeyRef, etc. */
- #else
- )
- #endif /* ST_KC_KEYS_NEED_REF */
+ SecKeyRef *privKeyRef) /* &ctx->signingPrivKeyRef, etc. */
{
CFIndex numCerts;
CFIndex cert;
SSLCertificate *certChain = NULL;
SSLCertificate *thisSslCert;
- SecKeychainRef kcRef;
OSStatus ortn;
SecIdentityRef identity;
SecCertificateRef certRef;
assert(ctx != NULL);
assert(destCert != NULL); /* though its referent may be NULL */
assert(pubKey != NULL);
- assert(privKey != NULL);
- assert(cspHand != NULL);
+ assert(privKeyRef != NULL);
sslDeleteCertificateChain(*destCert, ctx);
*destCert = NULL;
*pubKey = NULL;
- *privKey = NULL;
- *cspHand = 0;
+ *privKeyRef = NULL;
if(certs == NULL) {
sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
/*
* Certs[0] is an SecIdentityRef from which we extract subject cert,
- * privKey, pubKey, and cspHand.
+ * privKeyRef, pubKey.
*
* 1. ensure the first element is a SecIdentityRef.
*/
}
/*
- * 2. Extract cert, keys, CSP handle and convert to local format.
+ * 2. Extract cert, keys and convert to local format.
*/
ortn = SecIdentityCopyCertificate(identity, &certRef);
if(ortn) {
(int)ortn);
return ortn;
}
- ortn = SecKeyGetCSSMKey(keyRef, (const CSSM_KEY **)privKey);
- if(ortn) {
- sslErrorLog("parseIncomingCerts: SecKeyGetCSSMKey err %d\n",
- (int)ortn);
- return ortn;
- }
- /* FIXME = release keyRef? */
+ *privKeyRef = keyRef;
/* obtain public key from cert */
ortn = SecCertificateGetCLHandle(certRef, &clHand);
return (OSStatus)crtn;
}
- /* obtain keychain from key, CSP handle from keychain */
- ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)keyRef, &kcRef);
- if(ortn) {
- sslErrorLog("parseIncomingCerts: SecKeychainItemCopyKeychain err %d\n",
- (int)ortn);
- return ortn;
- }
- ortn = SecKeychainGetCSPHandle(kcRef, cspHand);
- if(ortn) {
- sslErrorLog("parseIncomingCerts: SecKeychainGetCSPHandle err %d\n",
- (int)ortn);
- return ortn;
- }
-
/* OK, that's the subject cert. Fetch optional remaining certs. */
/*
* Convert: CFArray of SecCertificateRefs --> chain of SSLCertificates.
certChain = thisSslCert;
}
- /* validate the whole mess, skipping host name verify */
- ortn = sslVerifyCertChain(ctx, *certChain, false);
- if(ortn) {
- goto errOut;
- }
-
/* SUCCESS */
*destCert = certChain;
return noErr;
return ortn;
}
-/*
- * Add Apple built-in root certs to ctx->trustedCerts.
- */
-OSStatus addBuiltInCerts (SSLContextRef ctx)
-{
- #if ST_MANAGES_TRUSTED_ROOTS
- OSStatus ortn;
- KCRef kc = nil;
-
- ortn = KCDispatch(kKCGetRootCertificateKeychain, &kc);
- if(ortn) {
- sslErrorLog("KCDispatch(kKCGetRootCertificateKeychain) returned %d\n",
- ortn);
- return ortn;
- }
- return parseTrustedKeychain(ctx, kc);
- #else
- /* nothing for now */
- return noErr;
- #endif /* ST_MANAGES_TRUSTED_ROOTS */
-}
-
-#if ST_MANAGES_TRUSTED_ROOTS
-
-/*
- * Given an open Keychain:
- * -- Get raw cert data, add to array of CSSM_DATAs in
- * ctx->trustedCerts
- * -- verify that each of these is a valid (self-verifying)
- * root cert
- * -- add each subject name to acceptableDNList
- */
-OSStatus
-parseTrustedKeychain (SSLContextRef ctx,
- KCRef keyChainRef)
-{
- CFMutableArrayRef kcCerts = NULL; /* all certs in one keychain */
- uint32 numGoodCerts = 0; /* # of good root certs */
- CSSM_DATA_PTR certData = NULL; /* array of CSSM_DATAs */
- CFIndex certDex; /* index into kcCerts */
- CFIndex certsPerKc; /* # of certs in this KC */
- OSStatus ortn;
- KCItemRef kcItem; /* one cert */
- Boolean goodCert;
-
- assert(ctx != NULL);
- if(keyChainRef == NULL) {
- return paramErr;
- }
-
- ortn = KCFindX509Certificates(keyChainRef,
- NULL, // name, XXX
- NULL, // emailAddress, XXX
- kCertSearchAny, // options
- &kcCerts); // results
- switch(ortn) {
- case noErr:
- break; // proceed
- case errKCItemNotFound:
- return noErr; // no certs; done
- default:
- sslErrorLog("parseTrustedKeychains: KCFindX509Certificates returned %d\n",
- ortn);
- return ortn;
- }
- if(kcCerts == NULL) {
- sslErrorLog("parseTrustedKeychains: no certs in KC\n");
- return noErr;
- }
-
- /* Note kcCerts must be released on any exit, successful or
- * otherwise. */
-
- certsPerKc = CFArrayGetCount(kcCerts);
-
- /*
- * This array gets allocd locally; we'll add it to
- * ctx->trustedCerts when we're done.
- */
- certData = sslMalloc(certsPerKc * sizeof(CSSM_DATA));
- if(certData == NULL) {
- ortn = memFullErr;
- goto errOut;
- }
- memset(certData, 0, certsPerKc * sizeof(CSSM_DATA));
-
- /*
- * Build up local certData one root cert at a time.
- * Some certs might not pass muster, hence the numGoodCerts
- * which may or may not increment each time thru.
- */
- for(certDex=0; certDex<certsPerKc; certDex++) {
- kcItem = (KCItemRef)CFArrayGetValueAtIndex(kcCerts, certDex);
- if(kcItem == NULL) {
- sslErrorLog("parseTrustedKeychains: CF error 1\n");
- ortn = errSSLInternal;
- goto errOut;
- }
- if(!KCIsRootCertificate(kcItem)) {
- /* not root, OK, skip to next cert */
- sslErrorLog("parseTrustedKeychains: cert %d NOT ROOT\n",
- certDex);
- continue;
- }
- ortn = addCertData(ctx,
- kcItem,
- &certData[numGoodCerts],
- &goodCert);
- if(ortn) {
- goto errOut;
- }
- if(goodCert) {
- /* added valid root to certData */
- numGoodCerts++;
- }
- } /* for each cert in kcCerts */
-
- #if SSL_DEBUG
- verifyTrustedRoots(ctx, certData, numGoodCerts);
- #endif
-
- /* Realloc ctx->trustedCerts, add new root certs */
- ctx->trustedCerts = sslRealloc(ctx->trustedCerts,
- ctx->numTrustedCerts * sizeof(CSSM_DATA),
- (ctx->numTrustedCerts + numGoodCerts) * sizeof(CSSM_DATA));
- if(ctx->trustedCerts == NULL) {
- ortn = memFullErr;
- goto errOut;
- }
- for(certDex=0; certDex<numGoodCerts; certDex++) {
- ctx->trustedCerts[ctx->numTrustedCerts + certDex] = certData[certDex];
- }
- ctx->numTrustedCerts += numGoodCerts;
- ortn = noErr;
-
- #if SSL_DEBUG
- verifyTrustedRoots(ctx, ctx->trustedCerts, ctx->numTrustedCerts);
- #endif
-
-errOut:
- sslFree(certData);
- if(kcCerts != NULL) {
- CFRelease(kcCerts);
- }
- return ortn;
-}
-
-/*
- * Given a (supposedly) root cert as a KCItemRef:
- * -- verify that the cert self-verifies
- * -- add its DER-encoded data *certData.
- * -- Add its subjectName to acceptableDNList.
- * -- If all is well, return True in *goodCert.
- *
- * The actual CSSM_DATA.Data is mallocd via CSSM_Malloc.
- */
-static OSStatus
-addCertData(
- SSLContext *ctx,
- KCItemRef kcItem,
- CSSM_DATA_PTR certData,
- Boolean *goodCert) /* RETURNED */
-{
- UInt32 certSize;
- OSStatus ortn;
- CSSM_BOOL subjectExpired;
-
- assert(ctx != NULL);
- assert(certData != NULL);
- assert(kcItem != NULL);
- assert(goodCert != NULL);
-
- *goodCert = false;
-
- /* how big is the cert? */
- ortn = KCGetData (kcItem, 0, NULL, &certSize);
- if(ortn != noErr) {
- sslErrorLog("addCertData: KCGetData(1) returned %d\n", ortn);
- return ortn;
- }
-
- /* Allocate the buffer. */
- ortn = stSetUpCssmData(certData, certSize);
- if(ortn) {
- return ortn;
- }
-
- /* Get the data. */
- ortn = KCGetData (kcItem, certSize, certData->Data, &certSize);
- if(ortn) {
- sslErrorLog("addCertData: KCGetData(2) returned %d\n", ortn);
- stFreeCssmData(certData, CSSM_FALSE);
- return ortn;
- }
-
- /*
- * Do actual cert verify, which
- * KCIsRootCertificate does not do. A failure isn't
- * fatal; we just don't add the cert to the array in
- * that case.
- *
- * FIXME - we assume here that our common cspHand can
- * do this cert verify; if not, we have some API work to
- * do (to let the caller specify which CSP to use with
- * trusted certs).
- */
- if(!sslVerifyCert(ctx,
- certData,
- certData,
- ctx->cspHand,
- &subjectExpired)) {
- sslErrorLog("addCertData: cert does not self-verify!\n");
- stFreeCssmData(certData, CSSM_FALSE);
- return noErr;
- }
-
- /* FIXME - needs update for MANAGES_TRUSTED_ROOTS */
- /* Add this cert's subject name to (poss. existing) acceptableDNList */
- CSSM_DATA_PTR dnData = sslGetCertSubjectName(ctx, certData);
- if(dnData) {
- DNListElem *dn = sslMalloc(sizeof(DNListElem));
- if(dn == NULL) {
- return memFullErr;
- }
- dn->next = ctx->acceptableDNList;
- ctx->acceptableDNList = dn;
-
- /* move actual data to dn; free the CSSM_DATA struct (must be
- * via CSSM_Free()!) */
- CSSM_TO_SSLBUF(dnData, &dn->derDN);
- sslFree(dnData);
- }
-
- *goodCert = true;
- return noErr;
-}
-
-/*
- * Given a newly encountered root cert (obtained from a peer's cert chain),
- * add it to newRootCertKc if the user so allows, and if so, add it to
- * trustedCerts.
- */
-OSStatus
-sslAddNewRoot(
- SSLContext *ctx,
- const CSSM_DATA_PTR rootCert)
-{
- KCRef defaultKc;
- Boolean bDefaultKcExists;
- KCItemRef certRef = NULL;
- OSStatus ortn;
- CSSM_DATA_PTR newTrustee;
- OSStatus serr;
-
- assert(ctx != NULL);
- assert(rootCert != NULL);
- assert(ctx->newRootCertKc != NULL); /* caller verifies this */
-
- /*
- * Get default KC, temporarily set new default.
- */
- ortn = KCGetDefaultKeychain(&defaultKc);
- if(ortn) {
- bDefaultKcExists = false;
- }
- else {
- bDefaultKcExists = true;
- }
- ortn = KCSetDefaultKeychain(ctx->newRootCertKc);
- if(ortn) {
- sslErrorLog("sslAddNewRoot: KCSetDefaultKeychain returned %d\n", ortn);
- return errSSLUnknownRootCert;
- }
-
- /*
- * Add cert to newRootCertKc. This may well fail due to user
- * interaction ("Do you want to add this root cert...?").
- */
- ortn = KCAddX509Certificate(rootCert->Data, rootCert->Length, &certRef);
-
- /* restore default KC in any case */
- if(bDefaultKcExists) {
- KCSetDefaultKeychain(defaultKc);
- }
- if(ortn) {
- sslErrorLog("sslAddNewRoot: KCAddX509Certificate returned %d\n", ortn);
- return errSSLUnknownRootCert;
- }
-
- /*
- * OK, user accepted new root. Now add to our private stash of
- * trusted roots. Realloc the whole pile...
- */
- ctx->trustedCerts = (CSSM_DATA_PTR)sslRealloc(ctx->trustedCerts,
- (ctx->numTrustedCerts * sizeof(CSSM_DATA)),
- ((ctx->numTrustedCerts + 1) * sizeof(CSSM_DATA)));
- if(ctx->trustedCerts == NULL) {
- return memFullErr;
- }
-
- /* Now add a copy of the new root. */
- newTrustee = &ctx->trustedCerts[ctx->numTrustedCerts];
- newTrustee->Data = NULL;
- newTrustee->Length = 0;
- serr = stSetUpCssmData(newTrustee, rootCert->Length);
- if(serr) {
- return serr;
- }
- BlockMove(rootCert->Data, newTrustee->Data, rootCert->Length);
- (ctx->numTrustedCerts)++;
- return noErr;
-}
-
-#endif /* ST_MANAGES_TRUSTED_ROOTS */