2 * Copyright (c) 2000-2013 Apple Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 * TPCertInfo.h - TP's private certificate info and cert group classes
23 #ifndef _TP_CERT_INFO_H_
24 #define _TP_CERT_INFO_H_
26 #include <Security/cssm.h>
27 #include <Security/SecTrust.h>
28 #include <Security/SecTrustSettings.h>
29 #include <security_utilities/alloc.h>
30 #include <security_utilities/threading.h>
31 #include <security_utilities/globalizer.h>
32 #include <CoreFoundation/CFDate.h>
34 /* protects TP-wide access to time() and gmtime() */
35 extern ModuleNexus
<Mutex
> tpTimeLock
;
38 * Prototypes for functions which are isomorphic between certs and CRLs at the
41 typedef CSSM_RETURN (*clGetFirstFieldFcn
)(
42 CSSM_CL_HANDLE CLHandle
,
43 CSSM_HANDLE ItemHandle
, // cached cert or CRL
44 const CSSM_OID
*ItemField
,
45 CSSM_HANDLE_PTR ResultsHandle
,
46 uint32
*NumberOfMatchedFields
,
47 CSSM_DATA_PTR
*Value
);
48 typedef CSSM_RETURN (*clAbortQueryFcn
)(
49 CSSM_CL_HANDLE CLHandle
,
50 CSSM_HANDLE ResultsHandle
); // from clGetFirstFieldFcn
51 typedef CSSM_RETURN (*clCacheItemFcn
)(
52 CSSM_CL_HANDLE CLHandle
,
53 const CSSM_DATA
*Item
, // raw cert or CRL
54 CSSM_HANDLE_PTR CertHandle
);
55 typedef CSSM_RETURN (*clAbortCacheFcn
)(
56 CSSM_CL_HANDLE CLHandle
,
57 CSSM_HANDLE ItemHandle
); // from clCacheItemFcn
58 typedef CSSM_RETURN (*clItemVfyFcn
)(
59 CSSM_CL_HANDLE CLHandle
,
60 CSSM_CC_HANDLE CCHandle
,
61 const CSSM_DATA
*CrlOrCertToBeVerified
,
62 const CSSM_DATA
*SignerCert
,
63 const CSSM_FIELD
*VerifyScope
,
67 /* CL/cert-specific functions */
68 clGetFirstFieldFcn getField
;
69 clAbortQueryFcn abortQuery
;
70 clCacheItemFcn cacheItem
;
71 clAbortCacheFcn abortCache
;
72 clItemVfyFcn itemVerify
;
73 /* CL/cert-specific OIDs */
74 const CSSM_OID
*notBeforeOid
;
75 const CSSM_OID
*notAfterOid
;
76 /* CL/cert specific errors */
77 CSSM_RETURN invalidItemRtn
; // CSSMERR_TP_INVALID_{CERT,CRL}_POINTER
78 CSSM_RETURN expiredRtn
;
79 CSSM_RETURN notValidYetRtn
;
85 * On construction of a TPClItemInfo, specifies whether or not to
86 * copy the incoming item data (in which we free it upon destruction)
87 * or to use caller's data as is (in which case the caller maintains
91 TIC_None
= 0, // never used
92 TIC_NoCopy
, // caller maintains
93 TIC_CopyData
// we copy and free
97 * State of a cert's mIsRoot flag. We do signature self-verify on demand.
100 TRS_Unknown
, // initial state
101 TRS_NamesMatch
, // subject == issuer, but no sig verify yet
102 TRS_NotRoot
, // subject != issuer, OR sig verify failed
103 TRS_IsRoot
// it's a root
107 * Base class for TPCertInfo and TPCrlInfo. Encapsulates caching of
108 * an entity within the CL, field lookup/free, and signature verify,
109 * all of which use similar functions at the CL API.
116 CSSM_CL_HANDLE clHand
,
117 CSSM_CSP_HANDLE cspHand
,
118 const TPClItemCalls
&clCalls
,
119 const CSSM_DATA
*itemData
,
120 TPItemCopy copyItemData
,
121 const char *verifyTime
); // may be NULL
124 void releaseResources();
127 * Fetch arbitrary field from cached item.
128 * Only should be used when caller is sure there is either zero or one
129 * of the requested fields present in the cert.
131 CSSM_RETURN
fetchField(
132 const CSSM_OID
*fieldOid
,
133 CSSM_DATA_PTR
*fieldData
); // mallocd by CL and RETURNED
135 /* free arbitrary field obtained from fetchField() */
136 CSSM_RETURN
freeField(
137 const CSSM_OID
*fieldOid
,
138 CSSM_DATA_PTR fieldData
);
141 * Verify with an issuer cert - works on certs and CRLs.
142 * Issuer/subject name match already performed by caller.
143 * May return CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE without
144 * performing a signature op, in which case it is the caller's
145 * resposibility to complete this operation later when
146 * sufficient information is available.
148 * Optional paramCert is used to provide parameters when issuer
149 * has a partial public key.
151 CSSM_RETURN
verifyWithIssuer(
152 TPCertInfo
*issuerCert
,
153 TPCertInfo
*paramCert
= NULL
) const;
156 CSSM_CL_HANDLE
clHand() const { return mClHand
; }
157 CSSM_CSP_HANDLE
cspHand() const { return mCspHand
; }
158 CSSM_HANDLE
cacheHand() const { return mCacheHand
; }
159 const CSSM_DATA
*itemData() const { return mItemData
; }
160 const CSSM_DATA
*issuerName() const { return mIssuerName
; };
161 const CSSM_DATA
*subjectKeyID() const { return mSubjectKeyID
; };
162 const CSSM_DATA
*authorityKeyID() const { return mAuthorityKeyID
; };
163 unsigned index() const { return mIndex
; }
164 void index(unsigned dex
) { mIndex
= dex
; }
165 bool isExpired() { return mIsExpired
; }
166 bool isNotValidYet() { return mIsNotValidYet
; }
169 * Calculate validity (not before/after). Returns
170 * CSSMERR_{TP_CERT,APPLETP_CRL}_NOT_VALID_YET
171 * CSSMERR_xxx_T_EXPIRED
173 * CSSMERR_xxx_INVALID_CERT_POINTER, other "bogus cert" errors
175 CSSM_RETURN
calculateCurrent(
176 const char *verifyString
= NULL
);
180 /* Tell CL to parse and cache the item */
181 CSSM_RETURN
cacheItem(
182 const CSSM_DATA
*itemData
,
183 TPItemCopy copyItemData
);
186 /* fetch not before/after fields */
187 void fetchNotBeforeAfter();
189 CSSM_CL_HANDLE mClHand
; // always valid
190 CSSM_CSP_HANDLE mCspHand
; // always valid
191 const TPClItemCalls
&mClCalls
;
192 bool mWeOwnTheData
; // if true, we have to free
194 /* following are valid subsequent to cacheItem(), generally
195 * called by subclass's constructor */
196 CSSM_HANDLE mCacheHand
;
197 CSSM_DATA_PTR mIssuerName
;
198 CSSM_DATA_PTR mSubjectKeyID
;
199 CSSM_DATA_PTR mAuthorityKeyID
;
200 CSSM_DATA_PTR mItemData
;
201 CSSM_ALGORITHMS mSigAlg
;
203 /* calculated implicitly at construction */
204 CFDateRef mNotBefore
;
207 /* also calculated at construction, but can be recalculated at will */
215 * Class representing one certificate. The raw cert data usually comes from
216 * a client (via incoming cert groups in CertGroupConstruct() and
217 * CertGroupVerify()); in this case, we don't own the raw data and
218 * don't copy or free it. Caller can optionally specify that we copy
219 * (and own and eventually free) the raw cert data. Currently this is
220 * done when we find a cert in a DlDb or from the net. The constructor throws
221 * on any error (bad cert data); subsequent to successful construction, no CSSM
222 * errors are thrown and it's guaranteed that the cert is basically good and
223 * successfully cached in the CL, and that we have a locally cached subject
224 * and issuer name (in normalized encoded format).
226 class TPCertInfo
: public TPClItemInfo
231 * No default constructor - this is the only way.
232 * This caches the cert and fetches subjectName and issuerName
233 * to ensure the incoming certData is well-constructed.
236 CSSM_CL_HANDLE clHand
,
237 CSSM_CSP_HANDLE cspHand
,
238 const CSSM_DATA
*certData
,
239 TPItemCopy copyCertData
,
241 const char *verifyTime
); // may be NULL
243 /* frees mSubjectName, mIssuerName, mCacheHand via mClHand */
247 const CSSM_DATA
*subjectName();
249 bool isSelfSigned(bool avoidVerify
= false);
251 bool isAnchor() { return mIsAnchor
; }
252 void isAnchor(bool a
) { mIsAnchor
= a
; }
253 bool isFromNet() { return mIsFromNet
; }
254 void isFromNet(bool n
) { mIsFromNet
= n
; };
255 bool isFromInputCerts() { return mIsFromInputCerts
; }
256 void isFromInputCerts(bool i
) { mIsFromInputCerts
= i
; }
257 unsigned numStatusCodes() { return mNumStatusCodes
; }
258 CSSM_RETURN
*statusCodes() { return mStatusCodes
; }
259 CSSM_DL_DB_HANDLE
dlDbHandle() { return mDlDbHandle
; }
260 void dlDbHandle(CSSM_DL_DB_HANDLE hand
)
261 { mDlDbHandle
= hand
; }
262 CSSM_DB_UNIQUE_RECORD_PTR
uniqueRecord()
263 { return mUniqueRecord
; }
264 void uniqueRecord(CSSM_DB_UNIQUE_RECORD_PTR rec
)
265 { mUniqueRecord
= rec
; }
266 CSSM_KEY_PTR
pubKey() { return mPublicKey
; }
267 bool used() { return mUsed
; }
268 void used(bool u
) { mUsed
= u
; }
269 bool isLeaf() { return mIsLeaf
; }
270 void isLeaf(bool l
) { mIsLeaf
= l
; }
272 SecTrustSettingsDomain
trustSettingsDomain() { return mTrustSettingsDomain
; }
273 SecTrustSettingsResult
trustSettingsResult() { return mTrustSettingsResult
; }
274 bool ignoredError() { return mIgnoredError
; }
276 /* true means "verification terminated due to user trust setting" */
277 bool trustSettingsFound();
279 * Am I the issuer of the specified subject item? Returns true if so.
280 * Works for subject certs as well as CRLs.
283 const TPClItemInfo
&subject
);
286 * Does my subject key id match the authority key id of the specified
287 * subject item? Returns true if so.
289 bool isAuthorityKeyOf(
290 const TPClItemInfo
&subject
);
293 * Add error status to mStatusCodes[]. Check to see if the
294 * added status is allowed per mAllowedErrs; if not return true.
295 * Returns false of the status *is* an allowed error.
301 * See if the specified error status is in the mStatusCodes array.
307 * See if the specified error status is allowed (return false) or
308 * fatal (return true) per mAllowedErrs[].
314 * Indicate whether this cert's public key is a CSSM_KEYATTR_PARTIAL
317 bool hasPartialKey();
319 /* Indicate whether this cert should be explicitly rejected.
324 * Flag to indicate that at least one revocation policy has successfully
325 * achieved a positive verification of the cert.
327 bool revokeCheckGood() { return mRevCheckGood
; }
328 void revokeCheckGood(bool b
) { mRevCheckGood
= b
; }
331 * Flag to indicate "I have successfully been checked for revocation
332 * status and the per-policy action data indicates that I need not be
333 * checked again by any other revocation policy". E.g.,
334 * CSSM_TP_ACTION_CRL_SUFFICIENT is set and CRL revocation checking
335 * was successful for this cert.
337 bool revokeCheckComplete() { return mRevCheckComplete
; }
338 void revokeCheckComplete(bool b
) { mRevCheckComplete
= b
; }
341 * Evaluate user trust; returns true if positive match found - i.e.,
342 * cert chain construction is done.
343 * The foundEntry return value indicates that *some* entry was found for
344 * the cert, regardless of the trust setting evaluation.
346 OSStatus
evaluateTrustSettings(
347 const CSSM_OID
&policyOid
,
348 const char *policyString
, // optional
349 uint32 policyStringLen
,
350 SecTrustSettingsKeyUsage keyUse
, // optional
351 bool *foundMatchingEntry
,
352 bool *foundEntry
); // RETURNED
354 bool hasEmptySubjectName();
356 /* Free mUniqueRecord if it exists */
357 void freeUniqueRecord();
360 /* obtained from CL at construction */
361 CSSM_DATA_PTR mSubjectName
; // always valid
362 CSSM_DATA_PTR mPublicKeyData
; // mPublicKey obtained from this field
363 CSSM_KEY_PTR mPublicKey
;
365 /* maintained by caller, default at constructor 0/false */
367 bool mIsFromInputCerts
;
369 unsigned mNumStatusCodes
;
370 CSSM_RETURN
*mStatusCodes
;
371 CSSM_DL_DB_HANDLE mDlDbHandle
;
372 CSSM_DB_UNIQUE_RECORD_PTR mUniqueRecord
;
373 bool mUsed
; // e.g., used in current loop
374 bool mIsLeaf
; // first in chain
375 TPRootState mIsRoot
; // subject == issuer
376 bool mRevCheckGood
; // >= 1 revoke check good
377 bool mRevCheckComplete
; // no more revoke checking needed
380 * When true, we've already called SecTrustSettingsEvaluateCert,
381 * and the cached results are in following member vars.
383 bool mTrustSettingsEvaluated
;
385 /* result of trust settings evaluation */
386 SecTrustSettingsDomain mTrustSettingsDomain
;
387 SecTrustSettingsResult mTrustSettingsResult
;
388 bool mTrustSettingsFoundAnyEntry
;
389 bool mTrustSettingsFoundMatchingEntry
;
391 /* allowed errors obtained from SecTrustSettingsEvaluateCert() */
392 CSSM_RETURN
*mAllowedErrs
;
393 uint32 mNumAllowedErrs
;
395 /* we actually ignored one of mAllowedErrors[] */
398 /* key usage for which mTrustSettingsResult was evaluated */
399 SecTrustSettingsKeyUsage mTrustSettingsKeyUsage
;
401 /* for SecTrustSettingsEvaluateCert() */
402 CFStringRef mCertHashStr
;
404 void releaseResources();
407 /* Describe who owns the items in a TP{Cert,Crl}Group */
409 TGO_None
= 0, // not used
410 TGO_Group
, // TP{Cert,Crl}Group owns the items
411 TGO_Caller
// caller owns the items
415 * TP's private Cert Group class. Provides a list of TPCertInfo pointers,
416 * to which caller can append additional elements, access an element at
417 * an arbitrary position, and remove an element at an arbitrary position.
424 * No default constructor.
425 * This one creates an empty TPCertGroup.
429 TPGroupOwner whoOwns
); // if TGO_Group, we delete
432 * Construct from unordered, untrusted CSSM_CERTGROUP. Resulting
433 * TPCertInfos are more or less in the same order as the incoming
434 * certs, though incoming certs are discarded if they don't parse.
435 * No verification of any sort is performed.
438 const CSSM_CERTGROUP
&CertGroupFrag
,
439 CSSM_CL_HANDLE clHand
,
440 CSSM_CSP_HANDLE cspHand
,
442 const char *verifyString
, // may be NULL
443 bool firstCertMustBeValid
,
444 TPGroupOwner whoOwns
);
447 * Deletes all TPCertInfo's.
452 * Construct ordered, verified cert chain from a variety of inputs.
453 * Time validity is ignored and needs to be checked by caller (it's
454 * stored in each TPCertInfo we add to ourself during construction).
455 * The only error returned is CSSMERR_APPLETP_INVALID_ROOT, meaning
456 * we verified back to a supposed root cert which did not in fact
457 * self-verify. Other interesting status is returned via the
458 * verifiedToRoot and verifiedToAnchor flags.
460 * NOTE: is it the caller's responsibility to call setAllUnused()
461 * for both incoming cert groups (inCertGroup and gatheredCerts).
462 * We don't do that here because we may call ourself recursively.
464 * subjectItem may or may not be in the cert group (currently, it
465 * is in the group if it's a cert and it's not if it's a CRL, but
466 * we don't rely on that).
468 CSSM_RETURN
buildCertGroup(
469 const TPClItemInfo
&subjectItem
, // Cert or CRL
470 TPCertGroup
*inCertGroup
, // optional
471 const CSSM_DL_DB_LIST
*dbList
, // optional
472 CSSM_CL_HANDLE clHand
,
473 CSSM_CSP_HANDLE cspHand
,
474 const char *verifyString
, // optional, for establishing
475 // validity of new TPCertInfos
476 /* trusted anchors, optional */
477 /* FIXME - maybe this should be a TPCertGroup */
478 uint32 numAnchorCerts
,
479 const CSSM_DATA
*anchorCerts
,
482 * Certs to be freed by caller (i.e., TPCertInfo which we allocate
483 * as a result of using a cert from anchorCerts or dbList) are added
486 TPCertGroup
&certsToBeFreed
,
489 * Other certificates gathered during the course of this operation,
490 * currently consisting of certs fetched from DBs and from the net.
491 * This is not used when called by AppleTPSession::CertGroupConstructPriv;
492 * it's an optimization for the case when we're building a cert group
493 * for TPCrlInfo::verifyWithContext - we avoid re-fetching certs from
494 * the net which are needed to verify both the subject cert and a CRL.
496 TPCertGroup
*gatheredCerts
,
499 * Indicates that subjectItem is a cert in this cert group.
500 * If true, that cert will be tested for "root-ness", including
501 * -- subject/issuer compare
502 * -- signature self-verify
505 CSSM_BOOL subjectIsInGroup
,
507 /* currently, only CSSM_TP_ACTION_FETCH_CERT_FROM_NET and
508 * CSSM_TP_ACTION_TRUST_SETTINGS are interesting */
509 CSSM_APPLE_TP_ACTION_FLAGS actionFlags
,
511 /* CSSM_TP_ACTION_TRUST_SETTINGS parameters */
512 const CSSM_OID
*policyOid
,
513 const char *policyStr
,
515 SecTrustSettingsKeyUsage leafKeyUse
,
518 CSSM_BOOL
&verifiedToRoot
, // end of chain self-verifies
519 CSSM_BOOL
&verifiedToAnchor
, // end of chain in anchors
520 CSSM_BOOL
&verifiedViaTrustSettings
); // chain ends per User Trust setting
522 /* add/remove/access TPTCertInfo's. */
524 TPCertInfo
*certInfo
); // appends to end of mCertInfo
525 TPCertInfo
*certAtIndex(
527 TPCertInfo
*removeCertAtIndex(
528 unsigned index
); // doesn't delete the cert, just
529 // removes it from our list
530 unsigned numCerts() const // how many do we have?
531 { return mNumCerts
; }
534 * Convenience accessors for first and last cert, only valid when we have
537 TPCertInfo
*firstCert();
538 TPCertInfo
*lastCert();
540 /* build a CSSM_CERTGROUP corresponding with our mCertInfo */
541 CSSM_CERTGROUP_PTR
buildCssmCertGroup();
543 /* build a CSSM_TP_APPLE_EVIDENCE_INFO array corresponding with our
545 CSSM_TP_APPLE_EVIDENCE_INFO
*buildCssmEvidenceInfo();
547 /* Given a status for basic construction of a cert group and a status
548 * of (optional) policy verification, plus the implicit notBefore/notAfter
549 * status in the certs, calculate a global return code. This just
550 * encapsulates a policy for CertGroupConstruct and CertGroupVerify.
552 CSSM_RETURN
getReturnCode(
553 CSSM_RETURN constructStatus
,
554 CSSM_RETURN policyStatus
,
555 CSSM_APPLE_TP_ACTION_FLAGS actionFlags
);
558 &alloc() {return mAlloc
; }
560 /* set all TPCertInfo.mUsed flags false */
563 /* free records obtained from DBs */
564 void freeDbRecords();
567 * See if the specified error status is allowed (return true) or
568 * fatal (return false) per each cert's mAllowedErrs[]. Returns
569 * true if any cert returns false for its isStatusFatal() call.
570 * The list of errors which can apply to cert-chain-wide allowedErrors
571 * is right here; if the incoming error is not in that list, we
572 * return false. If the incoming error code is CSSM_OK we return
573 * true as a convenience for our callers.
579 * Determine if we already have the specified cert in this group.
581 bool isInGroup(TPCertInfo
&certInfo
);
584 * Given a constructed cert group, encode all the issuers
585 * (i.e. chain minus the leaf, unless numCerts() is 1) as a PEM data blob.
586 * Caller is responsible for freeing the data.
588 void encodeIssuers(CSSM_DATA
&issuers
);
593 * Search unused incoming certs to find an issuer of specified
595 * WARNING this assumes a valied "used" state for all certs
597 * If partialIssuerKey is true on return, caller must re-verify signature
598 * of subject later when sufficient info is available.
600 TPCertInfo
*findIssuerForCertOrCrl(
601 const TPClItemInfo
&subject
,
602 bool &partialIssuerKey
);
605 * Called from buildCertGroup as final processing of a constructed
606 * group when CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE has been
607 * detected. Perform partial public key processing.
609 * CSSMERR_TP_CERTIFICATE_CANT_OPERATE - can't complete partial key
610 * CSSMERR_TP_INVALID_CERT_AUTHORITY - sig verify failed with
611 * (supposedly) completed partial key
613 CSSM_RETURN
verifyWithPartialKeys(
614 const TPClItemInfo
&subjectItem
); // Cert or CRL
617 TPCertInfo
**mCertInfo
; // just an array of pointers
618 unsigned mNumCerts
; // valid certs in certInfo
619 unsigned mSizeofCertInfo
; // mallocd space in certInfo
620 TPGroupOwner mWhoOwns
; // if TGO_Group, we delete certs
623 #endif /* _TP_CERT_INFO_H_ */