+++ /dev/null
-/*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please
- * obtain a copy of the License at http://www.apple.com/publicsource and
- * read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please
- * see the License for the specific language governing rights and
- * limitations under the License.
- */
-
-
-/*
- File: rootCerts.cp
-
- Contains: Bridge between SecTrustGetCSSMAnchorCertificates() and
- TP's internally cached tpRootCert array.
-
- Written by: Doug Mitchell.
-
- Copyright: Copyright 2002 by Apple Computer, Inc., all rights reserved.
-
-*/
-
-#include "rootCerts.h"
-
-#if TP_ROOT_CERT_ENABLE
-
-#include "certGroupUtils.h"
-#include "tpdebugging.h"
-#include <Security/Trust.h>
-#include <Security/TrustStore.h>
-#include <Security/debugging.h>
-#include <Security/oidscert.h>
-
-/* static in TPRootStore */
-ModuleNexus<TPRootStore> TPRootStore::tpGlobalRoots;
-
-TPRootStore::~TPRootStore()
-{
- /*
- * Technically this never gets called because the only instance
- * of a TPRootStore is via tpGlobalRoots. Freeing mRootCerts
- * here really doesn't accomplish anything.
- */
-}
-
-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; // copy to mRootCerts on success
- unsigned numTpRoots = 0;
-
- try {
- /* Obtain system-wide root certs in blob format */
- Security::KeychainCore::TrustStore &trustStore =
- Security::KeychainCore::Trust::gStore();
- trustStore.getCssmRootCertificates(roots);
- if(roots.type() != CSSM_CERTGROUP_DATA) {
- secdebug("tpAnchor", "Bad certGroup Type (%d)\n",
- (int)roots.type());
- return NULL;
- }
- numTpRoots = roots.count();
- if(numTpRoots == 0) {
- secdebug("tpAnchor", "empty certGroup\n");
- return NULL;
- }
-
- /* set up tpRoots array, one for each cert in the group */
- 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]);
-
- /* extract normalized subject name */
- CSSM_DATA *field;
- CSSM_HANDLE ResultsHandle;
- uint32 numFields;
- CSSM_RETURN crtn;
- crtn = CSSM_CL_CertGetFirstFieldValue(
- clHand,
- certData,
- &CSSMOID_X509V1SubjectName,
- &ResultsHandle,
- &numFields,
- &field);
- if(crtn) {
- secdebug("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);
-
- /* extract public key info - the blob and key size in bits */
- CSSM_KEY_PTR key;
- crtn = CSSM_CL_CertGetKeyInfo(clHand, certData, &key);
- if(crtn) {
- secdebug("tpAnchor", "CSSM_CL_CertGetKeyInfo error on cert %u",
- (unsigned)certNum);
- /* clear out this tpRoot? */
- continue;
- }
- tpCopyCssmData(alloc, &key->KeyData, &tpRoot->publicKey);
- tpRoot->keySize = key->KeyHeader.LogicalKeySizeInBits;
-
- /* A hole in the CDSA API: there is no free function at the
- * CL API for this key. It got mallocd with clHand's
- * allocator....
- */
- CSSM_API_MEMORY_FUNCS memFuncs;
- crtn = CSSM_GetAPIMemoryFunctions(clHand, &memFuncs);
- if(crtn) {
- secdebug("tpAnchor", "CSSM_GetAPIMemoryFunctions error");
- /* Oh well.. */
- continue;
- }
- memFuncs.free_func(key->KeyData.Data, memFuncs.AllocRef);
- memFuncs.free_func(key, memFuncs.AllocRef);
- } /* main loop */
- }
- catch(...) {
- /* TBD */
- return NULL;
- }
- mNumRootCerts = numTpRoots;
- numRootCerts = mNumRootCerts;
- mRootCerts = tpRoots;
- return mRootCerts;
-}
-
-/*
- * Compare a root cert to a list of known embedded roots.
- */
-CSSM_BOOL tp_isKnownRootCert(
- TPCertInfo *rootCert, // raw cert to compare
- CSSM_CL_HANDLE clHand)
-{
- const CSSM_DATA *subjectName = NULL;
- CSSM_DATA_PTR publicKey = NULL;
- unsigned dex;
- CSSM_BOOL brtn = CSSM_FALSE;
- CSSM_DATA_PTR valToFree = NULL;
- const tpRootCert *roots;
- unsigned numRoots;
-
- roots = TPRootStore::tpGlobalRoots().rootCerts(clHand, numRoots);
-
- subjectName = rootCert->subjectName();
- publicKey = tp_CertGetPublicKey(rootCert, &valToFree);
- if(publicKey == NULL) {
- tpPolicyError("tp_isKnownRootCert: error retrieving public "
- "key info!");
- goto errOut;
- }
-
- /*
- * Grind thru the list of known certs, demanding perfect match of
- * both fields
- */
- for(dex=0; dex<numRoots; dex++) {
- if(!tpCompareCssmData(subjectName,
- &roots[dex].subjectName)) {
- continue;
- }
- if(!tpCompareCssmData(publicKey,
- &roots[dex].publicKey)) {
- continue;
- }
- brtn = CSSM_TRUE;
- break;
- }
-errOut:
- tp_CertFreePublicKey(rootCert->clHand(), valToFree);
- return brtn;
-}
-
-/*
- * Attempt to verify specified cert (from the end of a chain) with one of
- * our known roots.
- */
-CSSM_BOOL tp_verifyWithKnownRoots(
- CSSM_CL_HANDLE clHand,
- CSSM_CSP_HANDLE cspHand,
- TPCertInfo *certToVfy) // last in chain, not root
-{
- CSSM_KEY rootKey; // pub key manufactured from tpRootCert info
- CSSM_CC_HANDLE ccHand; // signature context
- CSSM_RETURN crtn;
- unsigned dex;
- const tpRootCert *rootInfo;
- CSSM_BOOL brtn = CSSM_FALSE;
- CSSM_KEYHEADER *hdr = &rootKey.KeyHeader;
- CSSM_X509_ALGORITHM_IDENTIFIER_PTR algId;
- CSSM_DATA_PTR valToFree = NULL;
- CSSM_ALGORITHMS sigAlg;
- const tpRootCert *rootCerts = NULL;
- unsigned numRootCerts = 0;
-
- memset(&rootKey, 0, sizeof(CSSM_KEY));
-
- /*
- * Get signature algorithm from subject key
- */
- algId = tp_CertGetAlgId(certToVfy, &valToFree);
- if(algId == NULL) {
- /* bad cert */
- return CSSM_FALSE;
- }
- /* subsequest errors to errOut: */
-
- /* map to key and signature algorithm */
- sigAlg = tpOidToAldId(&algId->algorithm, &hdr->AlgorithmId);
- if(sigAlg == CSSM_ALGID_NONE) {
- tpPolicyError("tp_verifyWithKnownRoots: unknown sig alg");
- goto errOut;
- }
-
- /* Set up other constant key fields */
- hdr->BlobType = CSSM_KEYBLOB_RAW;
- switch(hdr->AlgorithmId) {
- case CSSM_ALGID_RSA:
- hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
- break;
- case CSSM_ALGID_DSA:
- hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
- break;
- case CSSM_ALGID_FEE:
- hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
- break;
- default:
- /* punt */
- hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
- }
- hdr->KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
- hdr->KeyAttr = CSSM_KEYATTR_MODIFIABLE | CSSM_KEYATTR_EXTRACTABLE;
- hdr->KeyUsage = CSSM_KEYUSE_VERIFY;
-
- rootCerts = TPRootStore::tpGlobalRoots().rootCerts(clHand, numRootCerts);
- for(dex=0; dex<numRootCerts; dex++) {
- rootInfo = &rootCerts[dex];
- if(!tpCompareCssmData(&rootInfo->subjectName, certToVfy->issuerName())) {
- /* not this root */
- continue;
- }
-
- /* only variation in key in the loop - raw key bits and size */
- rootKey.KeyData = rootInfo->publicKey;
- hdr->LogicalKeySizeInBits = rootInfo->keySize;
- crtn = CSSM_CSP_CreateSignatureContext(cspHand,
- sigAlg,
- NULL, // AcccedCred
- &rootKey,
- &ccHand);
- if(crtn) {
- tpPolicyError("tp_verifyWithKnownRoots: "
- "CSSM_CSP_CreateSignatureContext err");
- CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR);
- }
- crtn = CSSM_CL_CertVerify(clHand,
- ccHand,
- certToVfy->itemData(),
- NULL, // no signer cert
- NULL, // VerifyScope
- 0); // ScopeSize
- CSSM_DeleteContext(ccHand);
- if(crtn == CSSM_OK) {
- /* success! */
- brtn = CSSM_TRUE;
- break;
- }
- }
-errOut:
- if(valToFree != NULL) {
- tp_CertFreeAlgId(clHand, valToFree);
- }
- return brtn;
-}
-
-#endif /* TP_ROOT_CERT_ENABLE */
-