#include "rootCerts.h"
#include "certGroupUtils.h"
#include <Security/Trust.h>
#include <Security/TrustStore.h>
#include <Security/debugging.h>
#include <Security/oidscert.h>
ModuleNexus<TPRootStore> TPRootStore::tpGlobalRoots;
TPRootStore::~TPRootStore()
{
}
const tpRootCert *TPRootStore::rootCerts(
CSSM_CL_HANDLE clHand,
unsigned &numRootCerts)
{
StLock<Mutex> _(mLock);
if(mRootCerts) {
numRootCerts = mNumRootCerts;
return mRootCerts;
}
CssmAllocator &alloc(CssmAllocator::standard());
CertGroup roots;
tpRootCert *tpRoots = NULL; unsigned numTpRoots = 0;
try {
Security::KeychainCore::TrustStore &trustStore =
Security::KeychainCore::Trust::gStore();
trustStore.getCssmRootCertificates(roots);
if(roots.type() != CSSM_CERTGROUP_DATA) {
debug("tpAnchor", "Bad certGroup Type (%d)\n",
(int)roots.type());
return NULL;
}
numTpRoots = roots.count();
if(numTpRoots == 0) {
debug("tpAnchor", "empty certGroup\n");
return NULL;
}
tpRoots =
(tpRootCert *)alloc.malloc(numTpRoots * sizeof(tpRootCert));
memset(tpRoots, 0, numTpRoots * sizeof(tpRootCert));
for(uint32 certNum=0; certNum<numTpRoots; certNum++) {
tpRootCert *tpRoot = &tpRoots[certNum];
const CSSM_DATA *certData = &((roots.blobCerts())[certNum]);
CSSM_DATA *field;
CSSM_HANDLE ResultsHandle;
uint32 numFields;
CSSM_RETURN crtn;
crtn = CSSM_CL_CertGetFirstFieldValue(
clHand,
certData,
&CSSMOID_X509V1SubjectName,
&ResultsHandle,
&numFields,
&field);
if(crtn) {
debug("tpAnchor", "GetFirstFieldValue error on cert %u",
(unsigned)certNum);
continue;
}
CSSM_CL_CertAbortQuery(clHand, ResultsHandle);
tpCopyCssmData(alloc, field, &tpRoot->subjectName);
CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SubjectName,
field);
CSSM_KEY_PTR key;
crtn = CSSM_CL_CertGetKeyInfo(clHand, certData, &key);
if(crtn) {
debug("tpAnchor", "CSSM_CL_CertGetKeyInfo error on cert %u",
(unsigned)certNum);
continue;
}
tpCopyCssmData(alloc, &key->KeyData, &tpRoot->publicKey);
tpRoot->keySize = key->KeyHeader.LogicalKeySizeInBits;
CSSM_API_MEMORY_FUNCS memFuncs;
crtn = CSSM_GetAPIMemoryFunctions(clHand, &memFuncs);
if(crtn) {
debug("tpAnchor", "CSSM_GetAPIMemoryFunctions error");
continue;
}
memFuncs.free_func(key->KeyData.Data, memFuncs.AllocRef);
memFuncs.free_func(key, memFuncs.AllocRef);
}
}
catch(...) {
return NULL;
}
mNumRootCerts = numTpRoots;
numRootCerts = mNumRootCerts;
mRootCerts = tpRoots;
return mRootCerts;
}