]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_apple_x509_tp/lib/TPCertInfo.h
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_apple_x509_tp / lib / TPCertInfo.h
diff --git a/Security/libsecurity_apple_x509_tp/lib/TPCertInfo.h b/Security/libsecurity_apple_x509_tp/lib/TPCertInfo.h
new file mode 100644 (file)
index 0000000..231bb87
--- /dev/null
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2000-2013 Apple 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.
+ */
+
+
+/*
+ * TPCertInfo.h - TP's private certificate info and cert group classes
+ */
+
+#ifndef        _TP_CERT_INFO_H_
+#define _TP_CERT_INFO_H_
+
+#include <Security/cssm.h>
+#include <Security/SecTrust.h>
+#include <Security/SecTrustSettings.h>
+#include <security_utilities/alloc.h>
+#include <security_utilities/threading.h>
+#include <security_utilities/globalizer.h>
+#include <CoreFoundation/CFDate.h>
+
+/* protects TP-wide access to time() and gmtime() */
+extern ModuleNexus<Mutex> tpTimeLock;
+
+/*
+ * Prototypes for functions which are isomorphic between certs and CRLs at the
+ * CL API.
+ */
+typedef CSSM_RETURN (*clGetFirstFieldFcn)(
+       CSSM_CL_HANDLE CLHandle,
+       CSSM_HANDLE ItemHandle,                 // cached cert or CRL
+       const CSSM_OID *ItemField,
+       CSSM_HANDLE_PTR ResultsHandle,
+       uint32 *NumberOfMatchedFields,
+       CSSM_DATA_PTR *Value);
+typedef CSSM_RETURN (*clAbortQueryFcn)(
+       CSSM_CL_HANDLE CLHandle,
+       CSSM_HANDLE ResultsHandle);             // from clGetFirstFieldFcn
+typedef CSSM_RETURN (*clCacheItemFcn)(
+       CSSM_CL_HANDLE CLHandle,
+       const CSSM_DATA *Item,                  // raw cert or CRL
+       CSSM_HANDLE_PTR CertHandle);
+typedef CSSM_RETURN (*clAbortCacheFcn)(
+       CSSM_CL_HANDLE CLHandle,
+       CSSM_HANDLE ItemHandle);                // from clCacheItemFcn
+typedef CSSM_RETURN (*clItemVfyFcn)(
+       CSSM_CL_HANDLE CLHandle,
+       CSSM_CC_HANDLE CCHandle,
+       const CSSM_DATA *CrlOrCertToBeVerified,
+       const CSSM_DATA *SignerCert,
+       const CSSM_FIELD *VerifyScope,
+       uint32 ScopeSize);
+
+typedef struct {
+       /* CL/cert-specific functions */
+       clGetFirstFieldFcn      getField;
+       clAbortQueryFcn         abortQuery;
+       clCacheItemFcn          cacheItem;
+       clAbortCacheFcn         abortCache;
+       clItemVfyFcn            itemVerify;
+       /* CL/cert-specific OIDs */
+       const CSSM_OID          *notBeforeOid;
+       const CSSM_OID          *notAfterOid;
+       /* CL/cert specific errors */
+       CSSM_RETURN                     invalidItemRtn; // CSSMERR_TP_INVALID_{CERT,CRL}_POINTER
+       CSSM_RETURN                     expiredRtn;
+       CSSM_RETURN                     notValidYetRtn;
+} TPClItemCalls;
+
+class TPCertInfo;
+
+/*
+ * On construction of a TPClItemInfo, specifies whether or not to
+ * copy the incoming item data (in which we free it upon destruction)
+ * or to use caller's data as is (in which case the caller maintains
+ * the data).
+ */
+typedef enum {
+       TIC_None = 0,           // never used
+       TIC_NoCopy,                     // caller maintains
+       TIC_CopyData            // we copy and free
+} TPItemCopy;
+
+/*
+ * State of a cert's mIsRoot flag. We do signature self-verify on demand.
+ */
+typedef enum {
+       TRS_Unknown,            // initial state
+       TRS_NamesMatch,         // subject == issuer, but no sig verify yet
+       TRS_NotRoot,            // subject != issuer, OR sig verify failed
+       TRS_IsRoot                      // it's a root
+} TPRootState;
+
+/*
+ * Base class for TPCertInfo and TPCrlInfo. Encapsulates caching of
+ * an entity within the CL, field lookup/free, and signature verify,
+ * all of which use similar functions at the CL API.
+ */
+class TPClItemInfo
+{
+       NOCOPY(TPClItemInfo)
+public:
+       TPClItemInfo(
+               CSSM_CL_HANDLE          clHand,
+               CSSM_CSP_HANDLE         cspHand,
+               const TPClItemCalls     &clCalls,
+               const CSSM_DATA         *itemData,
+               TPItemCopy                      copyItemData,
+               const char                      *verifyTime);           // may be NULL
+
+       ~TPClItemInfo();
+       void releaseResources();
+
+       /*
+        * Fetch arbitrary field from cached item.
+        * Only should be used when caller is sure there is either zero or one
+        * of the requested fields present in the cert.
+        */
+       CSSM_RETURN fetchField(
+               const CSSM_OID  *fieldOid,
+               CSSM_DATA_PTR   *fieldData);                    // mallocd by CL and RETURNED
+
+       /* free arbitrary field obtained from fetchField() */
+       CSSM_RETURN freeField(
+               const CSSM_OID  *fieldOid,
+               CSSM_DATA_PTR   fieldData);
+
+       /*
+        * Verify with an issuer cert - works on certs and CRLs.
+        * Issuer/subject name match already performed by caller.
+        * May return CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE without
+        * performing a signature op, in which case it is the caller's
+        * resposibility to complete this operation later when
+        * sufficient information is available.
+        *
+        * Optional paramCert is used to provide parameters when issuer
+        * has a partial public key.
+        */
+       CSSM_RETURN verifyWithIssuer(
+               TPCertInfo              *issuerCert,
+               TPCertInfo              *paramCert = NULL) const;
+
+       /* accessors */
+       CSSM_CL_HANDLE  clHand()                const { return mClHand; }
+       CSSM_CSP_HANDLE cspHand()               const { return mCspHand; }
+       CSSM_HANDLE             cacheHand()             const { return mCacheHand; }
+       const CSSM_DATA *itemData()             const { return mItemData; }
+       const CSSM_DATA *issuerName()   const { return mIssuerName; };
+       const CSSM_DATA *subjectKeyID() const { return mSubjectKeyID; };
+       const CSSM_DATA *authorityKeyID()       const { return mAuthorityKeyID; };
+       unsigned                index()                 const { return mIndex; }
+       void                    index(unsigned dex)       { mIndex = dex; }
+       bool                    isExpired()                       { return mIsExpired; }
+       bool                    isNotValidYet()           { return mIsNotValidYet; }
+
+       /*
+        * Calculate validity (not before/after). Returns
+        *              CSSMERR_{TP_CERT,APPLETP_CRL}_NOT_VALID_YET
+        *              CSSMERR_xxx_T_EXPIRED
+        *              CSSM_OK
+        *              CSSMERR_xxx_INVALID_CERT_POINTER, other "bogus cert" errors
+        */
+       CSSM_RETURN calculateCurrent(
+               const char                      *verifyString = NULL);
+
+private:
+
+       /* Tell CL to parse and cache the item */
+       CSSM_RETURN cacheItem(
+               const CSSM_DATA         *itemData,
+               TPItemCopy                      copyItemData);
+
+
+       /* fetch not before/after fields */
+       void fetchNotBeforeAfter();
+
+       CSSM_CL_HANDLE                  mClHand;                                // always valid
+       CSSM_CSP_HANDLE                 mCspHand;                               // always valid
+       const TPClItemCalls             &mClCalls;
+       bool                                    mWeOwnTheData;                  // if true, we have to free
+                                                                                                       //    mCertData
+       /* following are valid subsequent to cacheItem(), generally
+        * called by subclass's constructor */
+       CSSM_HANDLE                             mCacheHand;
+       CSSM_DATA_PTR                   mIssuerName;
+       CSSM_DATA_PTR                   mSubjectKeyID;
+       CSSM_DATA_PTR                   mAuthorityKeyID;
+       CSSM_DATA_PTR                   mItemData;
+       CSSM_ALGORITHMS                 mSigAlg;
+
+       /* calculated implicitly at construction */
+       CFDateRef                               mNotBefore;
+       CFDateRef                               mNotAfter;
+
+       /* also calculated at construction, but can be recalculated at will */
+       bool                                    mIsExpired;
+       bool                                    mIsNotValidYet;
+
+       unsigned                                mIndex;
+};
+
+/*
+ * Class representing one certificate. The raw cert data usually comes from
+ * a client (via incoming cert groups in CertGroupConstruct() and
+ * CertGroupVerify()); in this case, we don't own the raw data and
+ * don't copy or free it. Caller can optionally specify that we copy
+ * (and own and eventually free) the raw cert data. Currently this is
+ * done when we find a cert in a DlDb or from the net. The constructor throws
+ * on any error (bad cert data); subsequent to successful construction, no CSSM
+ * errors are thrown and it's guaranteed that the cert is basically good and
+ * successfully cached in the CL, and that we have a locally cached subject
+ * and issuer name (in normalized encoded format).
+ */
+class TPCertInfo : public TPClItemInfo
+{
+       NOCOPY(TPCertInfo)
+public:
+       /*
+        * No default constructor - this is the only way.
+        * This caches the cert and fetches subjectName and issuerName
+        * to ensure the incoming certData is well-constructed.
+        */
+       TPCertInfo(
+               CSSM_CL_HANDLE          clHand,
+               CSSM_CSP_HANDLE         cspHand,
+               const CSSM_DATA         *certData,
+               TPItemCopy                      copyCertData,
+
+               const char                      *verifyTime);           // may be NULL
+
+       /* frees mSubjectName, mIssuerName, mCacheHand via mClHand */
+       ~TPCertInfo();
+
+       /* accessors */
+       const CSSM_DATA *subjectName();
+
+       bool            isSelfSigned(bool avoidVerify = false);
+
+       bool            isAnchor()                              { return mIsAnchor; }
+       void            isAnchor(bool a)                { mIsAnchor = a; }
+       bool            isFromNet()                             { return mIsFromNet; }
+       void            isFromNet(bool n)               { mIsFromNet = n; };
+       bool            isFromInputCerts()              { return mIsFromInputCerts; }
+       void            isFromInputCerts(bool i) { mIsFromInputCerts = i; }
+       unsigned        numStatusCodes()                { return mNumStatusCodes; }
+       CSSM_RETURN     *statusCodes()                  { return mStatusCodes; }
+       CSSM_DL_DB_HANDLE dlDbHandle()          { return mDlDbHandle; }
+       void dlDbHandle(CSSM_DL_DB_HANDLE hand)
+                                                                               { mDlDbHandle = hand; }
+       CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord()
+                                                                               { return mUniqueRecord; }
+       void uniqueRecord(CSSM_DB_UNIQUE_RECORD_PTR rec)
+                                                                               { mUniqueRecord = rec; }
+       CSSM_KEY_PTR pubKey()                           { return mPublicKey; }
+       bool            used()                                  { return mUsed; }
+       void            used(bool u)                    { mUsed = u; }
+       bool            isLeaf()                                { return mIsLeaf; }
+       void            isLeaf(bool l)                  { mIsLeaf = l; }
+
+       SecTrustSettingsDomain  trustSettingsDomain() { return mTrustSettingsDomain; }
+       SecTrustSettingsResult trustSettingsResult() { return mTrustSettingsResult; }
+       bool ignoredError()                                     { return mIgnoredError; }
+
+       /* true means "verification terminated due to user trust setting" */
+       bool            trustSettingsFound();
+       /*
+        * Am I the issuer of the specified subject item? Returns true if so.
+        * Works for subject certs as well as CRLs.
+        */
+       bool isIssuerOf(
+               const TPClItemInfo      &subject);
+
+       /*
+        * Does my subject key id match the authority key id of the specified
+        * subject item? Returns true if so.
+        */
+       bool isAuthorityKeyOf(
+               const TPClItemInfo      &subject);
+
+       /*
+        * Add error status to mStatusCodes[]. Check to see if the
+        * added status is allowed per mAllowedErrs; if not return true.
+        * Returns false of the status *is* an allowed error.
+        */
+       bool addStatusCode(
+               CSSM_RETURN             code);
+
+       /*
+        * See if the specified error status is in the mStatusCodes array.
+        */
+       bool hasStatusCode(
+               CSSM_RETURN                     code);
+
+       /*
+        * See if the specified error status is allowed (return false) or
+        * fatal (return true) per mAllowedErrs[].
+        */
+       bool isStatusFatal(
+               CSSM_RETURN                     code);
+
+       /*
+        * Indicate whether this cert's public key is a CSSM_KEYATTR_PARTIAL
+        * key.
+        */
+       bool                                    hasPartialKey();
+
+       /* Indicate whether this cert should be explicitly rejected.
+        */
+       bool                                    shouldReject();
+
+       /*
+        * Flag to indicate that at least one revocation policy has successfully
+        * achieved a positive verification of the cert.
+        */
+       bool                            revokeCheckGood()                       { return mRevCheckGood; }
+       void                            revokeCheckGood(bool b)         { mRevCheckGood = b; }
+
+       /*
+        * Flag to indicate "I have successfully been checked for revocation
+        * status and the per-policy action data indicates that I need not be
+        * checked again by any other revocation policy". E.g.,
+        * CSSM_TP_ACTION_CRL_SUFFICIENT is set and CRL revocation checking
+        * was successful for this cert.
+        */
+       bool                            revokeCheckComplete()           { return mRevCheckComplete; }
+       void                            revokeCheckComplete(bool b)     { mRevCheckComplete = b; }
+
+       /*
+        * Evaluate user trust; returns true if positive match found - i.e.,
+        * cert chain construction is done.
+        * The foundEntry return value indicates that *some* entry was found for
+        * the cert, regardless of the trust setting evaluation.
+        */
+       OSStatus evaluateTrustSettings(
+                               const CSSM_OID                  &policyOid,
+                               const char                              *policyString,          // optional
+                               uint32                                  policyStringLen,
+                               SecTrustSettingsKeyUsage keyUse,                                // optional
+                               bool                                    *foundMatchingEntry,
+                               bool                                    *foundEntry);           // RETURNED
+
+       bool                            hasEmptySubjectName();
+
+       /* Free mUniqueRecord if it exists */
+       void    freeUniqueRecord();
+
+private:
+       /* obtained from CL at construction */
+       CSSM_DATA_PTR                   mSubjectName;           // always valid
+       CSSM_DATA_PTR                   mPublicKeyData;         // mPublicKey obtained from this field
+       CSSM_KEY_PTR                    mPublicKey;
+
+       /* maintained by caller, default at constructor 0/false */
+       bool                                    mIsAnchor;
+       bool                                    mIsFromInputCerts;
+       bool                                    mIsFromNet;
+       unsigned                                mNumStatusCodes;
+       CSSM_RETURN                             *mStatusCodes;
+       CSSM_DL_DB_HANDLE               mDlDbHandle;
+       CSSM_DB_UNIQUE_RECORD_PTR mUniqueRecord;
+       bool                                    mUsed;                  // e.g., used in current loop
+       bool                                    mIsLeaf;                // first in chain
+       TPRootState                             mIsRoot;                // subject == issuer
+       bool                                    mRevCheckGood;          // >= 1 revoke check good
+       bool                                    mRevCheckComplete;      // no more revoke checking needed
+
+       /*
+        * When true, we've already called SecTrustSettingsEvaluateCert,
+        * and the cached results are in following member vars.
+        */
+       bool                                    mTrustSettingsEvaluated;
+
+       /* result of trust settings evaluation */
+       SecTrustSettingsDomain  mTrustSettingsDomain;
+       SecTrustSettingsResult  mTrustSettingsResult;
+       bool                                    mTrustSettingsFoundAnyEntry;
+       bool                                    mTrustSettingsFoundMatchingEntry;
+
+       /* allowed errors obtained from SecTrustSettingsEvaluateCert() */
+       CSSM_RETURN                             *mAllowedErrs;
+       uint32                                  mNumAllowedErrs;
+
+       /* we actually ignored one of mAllowedErrors[] */
+       bool                                    mIgnoredError;
+
+       /* key usage for which mTrustSettingsResult was evaluated */
+       SecTrustSettingsKeyUsage mTrustSettingsKeyUsage;
+
+       /* for SecTrustSettingsEvaluateCert() */
+       CFStringRef                             mCertHashStr;
+
+       void                                    releaseResources();
+};
+
+/* Describe who owns the items in a TP{Cert,Crl}Group */
+typedef enum {
+       TGO_None = 0,           // not used
+       TGO_Group,                      // TP{Cert,Crl}Group owns the items
+       TGO_Caller                      // caller owns the items
+} TPGroupOwner;
+
+/*
+ * TP's private Cert Group class. Provides a list of TPCertInfo pointers,
+ * to which caller can append additional elements, access an element at
+ * an arbitrary position, and remove an element at an arbitrary position.
+ */
+class TPCertGroup
+{
+       NOCOPY(TPCertGroup)
+public:
+       /*
+        * No default constructor.
+        * This one creates an empty TPCertGroup.
+        */
+       TPCertGroup(
+               Allocator                       &alloc,
+               TPGroupOwner            whoOwns);               // if TGO_Group, we delete
+
+       /*
+        * Construct from unordered, untrusted CSSM_CERTGROUP. Resulting
+        * TPCertInfos are more or less in the same order as the incoming
+        * certs, though incoming certs are discarded if they don't parse.
+        * No verification of any sort is performed.
+        */
+       TPCertGroup(
+               const CSSM_CERTGROUP    &CertGroupFrag,
+               CSSM_CL_HANDLE                  clHand,
+               CSSM_CSP_HANDLE                 cspHand,
+               Allocator                               &alloc,
+               const char                              *verifyString,                  // may be NULL
+               bool                                    firstCertMustBeValid,
+               TPGroupOwner                    whoOwns);
+
+       /*
+        * Deletes all TPCertInfo's.
+        */
+       ~TPCertGroup();
+
+       /*
+        * Construct ordered, verified cert chain from a variety of inputs.
+        * Time validity is ignored and needs to be checked by caller (it's
+        * stored in each TPCertInfo we add to ourself during construction).
+        * The only error returned is CSSMERR_APPLETP_INVALID_ROOT, meaning
+        * we verified back to a supposed root cert which did not in fact
+        * self-verify. Other interesting status is returned via the
+        * verifiedToRoot and verifiedToAnchor flags.
+        *
+        * NOTE: is it the caller's responsibility to call setAllUnused()
+        * for both incoming cert groups (inCertGroup and gatheredCerts).
+        * We don't do that here because we may call ourself recursively.
+        *
+        * subjectItem may or may not be in the cert group (currently, it
+        * is in the group if it's a cert and it's not if it's a CRL, but
+        * we don't rely on that).
+        */
+       CSSM_RETURN buildCertGroup(
+               const TPClItemInfo              &subjectItem,   // Cert or CRL
+               TPCertGroup                             *inCertGroup,   // optional
+               const CSSM_DL_DB_LIST   *dbList,                // optional
+               CSSM_CL_HANDLE                  clHand,
+               CSSM_CSP_HANDLE                 cspHand,
+               const char                              *verifyString,  // optional, for establishing
+                                                                                               //   validity of new TPCertInfos
+               /* trusted anchors, optional */
+               /* FIXME - maybe this should be a TPCertGroup */
+               uint32                                  numAnchorCerts,
+               const CSSM_DATA                 *anchorCerts,
+
+               /*
+                * Certs to be freed by caller (i.e., TPCertInfo which we allocate
+                * as a result of using a cert from anchorCerts or dbList) are added
+                * to this group.
+                */
+               TPCertGroup                             &certsToBeFreed,
+
+               /*
+               * Other certificates gathered during the course of this operation,
+               * currently consisting of certs fetched from DBs and from the net.
+               * This is not used when called by AppleTPSession::CertGroupConstructPriv;
+               * it's an optimization for the case when we're building a cert group
+               * for TPCrlInfo::verifyWithContext - we avoid re-fetching certs from
+               * the net which are needed to verify both the subject cert and a CRL.
+               */
+               TPCertGroup                             *gatheredCerts,
+
+               /*
+               * Indicates that subjectItem is a cert in this cert group.
+               * If true, that cert will be tested for "root-ness", including
+               *   -- subject/issuer compare
+               *   -- signature self-verify
+               *   -- anchor compare
+               */
+               CSSM_BOOL                               subjectIsInGroup,
+
+               /* currently, only CSSM_TP_ACTION_FETCH_CERT_FROM_NET and
+                * CSSM_TP_ACTION_TRUST_SETTINGS are interesting */
+               CSSM_APPLE_TP_ACTION_FLAGS      actionFlags,
+
+               /* CSSM_TP_ACTION_TRUST_SETTINGS parameters */
+               const CSSM_OID                  *policyOid,
+               const char                              *policyStr,
+               uint32                                  policyStrLen,
+               SecTrustSettingsKeyUsage        leafKeyUse,
+
+               /* returned */
+               CSSM_BOOL                               &verifiedToRoot,                // end of chain self-verifies
+               CSSM_BOOL                               &verifiedToAnchor,              // end of chain in anchors
+               CSSM_BOOL                               &verifiedViaTrustSettings);     // chain ends per User Trust setting
+
+       /* add/remove/access TPTCertInfo's. */
+       void appendCert(
+               TPCertInfo                      *certInfo);                     // appends to end of mCertInfo
+       TPCertInfo *certAtIndex(
+               unsigned                        index);
+       TPCertInfo *removeCertAtIndex(
+               unsigned                        index);                         // doesn't delete the cert, just
+                                                                                               // removes it from our list
+       unsigned numCerts() const                                       // how many do we have?
+               { return mNumCerts; }
+
+       /*
+        * Convenience accessors for first and last cert, only valid when we have
+        * at least one cert.
+        */
+       TPCertInfo *firstCert();
+       TPCertInfo *lastCert();
+
+       /* build a CSSM_CERTGROUP corresponding with our mCertInfo */
+       CSSM_CERTGROUP_PTR buildCssmCertGroup();
+
+       /* build a CSSM_TP_APPLE_EVIDENCE_INFO array corresponding with our
+        * mCertInfo */
+       CSSM_TP_APPLE_EVIDENCE_INFO *buildCssmEvidenceInfo();
+
+       /* Given a status for basic construction of a cert group and a status
+        * of (optional) policy verification, plus the implicit notBefore/notAfter
+        * status in the certs, calculate a global return code. This just
+        * encapsulates a policy for CertGroupConstruct and CertGroupVerify.
+        */
+       CSSM_RETURN getReturnCode(
+               CSSM_RETURN                                     constructStatus,
+               CSSM_RETURN                                     policyStatus,
+               CSSM_APPLE_TP_ACTION_FLAGS      actionFlags);
+
+       Allocator
+               &alloc() {return mAlloc; }
+
+       /* set all TPCertInfo.mUsed flags false */
+       void                                    setAllUnused();
+
+       /* free records obtained from DBs */
+       void                                    freeDbRecords();
+
+       /*
+        * See if the specified error status is allowed (return true) or
+        * fatal (return false) per each cert's mAllowedErrs[]. Returns
+        * true if any cert returns false for its isStatusFatal() call.
+        * The list of errors which can apply to cert-chain-wide allowedErrors
+        * is right here; if the incoming error is not in that list, we
+        * return false. If the incoming error code is CSSM_OK we return
+        * true as a convenience for our callers.
+        */
+       bool isAllowedError(
+               CSSM_RETURN     code);
+
+       /*
+        * Determine if we already have the specified cert in this group.
+        */
+       bool isInGroup(TPCertInfo &certInfo);
+
+       /*
+        * Given a constructed cert group, encode all the issuers
+        * (i.e. chain minus the leaf, unless numCerts() is 1) as a PEM data blob.
+        * Caller is responsible for freeing the data.
+        */
+       void encodeIssuers(CSSM_DATA &issuers);
+
+private:
+
+       /*
+        * Search unused incoming certs to find an issuer of specified
+        * cert or CRL.
+        * WARNING this assumes a valied "used" state for all certs
+        * in this group.
+        * If partialIssuerKey is true on return, caller must re-verify signature
+     * of subject later when sufficient info is available.
+        */
+       TPCertInfo *findIssuerForCertOrCrl(
+               const TPClItemInfo      &subject,
+               bool                            &partialIssuerKey);
+
+       /*
+        * Called from buildCertGroup as final processing of a constructed
+        * group when CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE has been
+        * detected. Perform partial public key processing.
+        * Returns:
+        *      CSSMERR_TP_CERTIFICATE_CANT_OPERATE - can't complete partial key
+        *              CSSMERR_TP_INVALID_CERT_AUTHORITY - sig verify failed with
+        *                      (supposedly) completed partial key
+        */
+       CSSM_RETURN                             verifyWithPartialKeys(
+               const TPClItemInfo      &subjectItem);          // Cert or CRL
+
+       Allocator                               &mAlloc;
+       TPCertInfo                              **mCertInfo;            // just an array of pointers
+       unsigned                                mNumCerts;                      // valid certs in certInfo
+       unsigned                                mSizeofCertInfo;        // mallocd space in certInfo
+       TPGroupOwner                    mWhoOwns;                       // if TGO_Group, we delete certs
+                                                                                               //    upon destruction
+};
+#endif /* _TP_CERT_INFO_H_ */