+++ /dev/null
-/*
- * 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_ */