]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_ocspd/common/ocspResponse.h
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_ocspd / common / ocspResponse.h
diff --git a/Security/libsecurity_ocspd/common/ocspResponse.h b/Security/libsecurity_ocspd/common/ocspResponse.h
new file mode 100644 (file)
index 0000000..5c0de2f
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved.
+ * 
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The 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.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * ocspResponse.h - OCSP Response class
+ */
+#ifndef        _OCSP_RESPONSE_H_
+#define _OCSP_RESPONSE_H_
+
+#include <security_ocspd/ocspExtensions.h>
+#include <Security/ocspTemplates.h>
+#include <Security/certextensions.h>
+#include <Security/SecAsn1Coder.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+/* used to indicate "I don't know the CRLReason" */
+#define CrlReason_NONE         ((CE_CrlReason)-1)
+
+/*
+ * CertIDs can be represented differently by two peers even though they refer to 
+ * the same cert. Client can use SHA1 hash and server can use MD5, for example. 
+ * So all of our code which creates a CertID based on known, existing subject and
+ * issuer certs uses one of these "smart" certIDs which can encode itself and also 
+ * compare against any form of existing SecAsn1OCSPCertID.
+ */
+class OCSPClientCertID
+{
+       NOCOPY(OCSPClientCertID);
+public:
+       /*
+        * Basic constructor given issuer's public key and name, and subject's
+        * serial number.
+        */
+       OCSPClientCertID(
+               const CSSM_DATA                 &issuerName,
+               const CSSM_DATA                 &issuerPubKey,
+               const CSSM_DATA                 &subjectSerial);
+               
+       ~OCSPClientCertID();
+       
+       /*
+        * DER encode.
+        */
+       const CSSM_DATA *encode();
+               
+       /*
+        * Does this object refer to the same cert as specified SecAsn1OCSPCertID?
+        * This is the main purpose of this class's existence; this function works 
+        * even if specified SecAsn1OCSPCertID uses a different hash algorithm
+        * than we do, since we keep copies of our basic components. 
+        *
+        * Returns true if compare successful.
+        */
+       bool compareToExist(
+               const SecAsn1OCSPCertID &exist);
+               
+       /* 
+        * Convenience function, like compareToExist, with a raw encoded CertID.
+        */
+       bool compareToExist( 
+               const CSSM_DATA &exist);
+               
+private:
+       CSSM_DATA mIssuerName;
+       CSSM_DATA mIssuerPubKey;
+       CSSM_DATA mSubjectSerial;
+       CSSM_DATA mEncoded;
+};
+
+/*
+ * Object representing one SecAsn1OCSPSingleResponse, i.e., the portion of 
+ * an OCSP response associated with a single CertID. These are created and
+ * vended solely by an OCSPResponse object. The client which gets them from
+ * an OCSPResponse (via singleResponse()) must delete the object when finished
+ * with it. 
+ */
+class OCSPSingleResponse
+{
+       NOCOPY(OCSPSingleResponse);
+public:
+       /* only OCSPResponse creates these */
+       ~OCSPSingleResponse();
+       friend class OCSPResponse;
+protected:
+       
+       OCSPSingleResponse(
+               SecAsn1OCSPSingleResponse       *resp);
+public:
+               SecAsn1OCSPCertStatusTag        certStatus()    { return mCertStatus; }
+               CFAbsoluteTime                          thisUpdate()    { return mThisUpdate; }
+               CFAbsoluteTime                          nextUpdate()    { return mNextUpdate; }
+               CFAbsoluteTime                          revokedTime()   { return mRevokedTime; }
+               CE_CrlReason                            crlReason()             { return mCrlReason; }
+               
+               /* Extension accessors - all are optional */
+               
+               /* CRL Reference */
+               const CSSM_DATA                         *crlUrl();
+               const CSSM_DATA                         *crlNum();
+               CFAbsoluteTime                          crlTime();                      /* may be NULL_TIME */
+               
+               /* archive cutoff */
+               CFAbsoluteTime                          archiveCutoff();
+               
+               /* service locator not implemented yet */
+private:
+               SecAsn1CoderRef                         mCoder;
+               SecAsn1OCSPCertStatusTag        mCertStatus;
+               CFAbsoluteTime                          mThisUpdate;
+               CFAbsoluteTime                          mNextUpdate;            /* may be NULL_TIME */
+               CFAbsoluteTime                          mRevokedTime;           /* != NULL_TIME for CS_Revoked */
+               CE_CrlReason                            mCrlReason;             
+               OCSPExtensions                          *mExtensions;
+};
+
+/*
+ * OCSPResponse maintains its own temporal validity status based on the values of 
+ * all of the enclosed SingleResponses' thisUpdate and (optional) nextUpdate
+ * fields, in addition to a default time-to-live (TTL) value passed to
+ * OCSPResponse's constructor.
+ *
+ * First, all of the thisUpdate fields are checked during OCSPResponse's constructor. 
+ * if any of these are later than the current time, the entire response is considered
+ * invalid and the constructor throws a CssmError(CSSMERR_APPLETP_OCSP_BAD_RESPONSE). 
+ * Subsequent to construction, all thisUpdate fields are ignored. 
+ *
+ * The NextUpdate times are handled as follows. 
+ *
+ * 1. An OCSPResponse's latestNextUpdate is defined as the latest of all of the 
+ *    nextUpdate fields in its SingleResponses. This is evaluated during construction. 
+ *
+ * 2. An OCSPResponse's latestNextUpdate is NULL_TIME if none of its SingleResponses 
+ *    contain any nextUpdate (this field is in fact optional). 
+ *
+ * 3. The caller of OCSPResponse's constructor passes in a default time-to-live 
+ *    (TTL) in seconds; call this defaultTTL. Call the time at which the 
+ *    constructor is called, PLUS defaultTTL, "defaultExpire".
+ * 
+ * -- If the OCSPResponse's latestNextUpdate is NULL_TIME then expireTime() returns
+ *    defaultExpire.
+ *
+ * -- Otherwise, expireTime() returns the lesser of (latestNextUpdate, 
+ *    defaultExpire).
+ *
+ * Note that this mechanism is used by both the TP's in-core cache and ocspd's
+ * on-disk cache; the two have different default TTLs values but the mechanism
+ * for calcuating expireTime() is identical. 
+ */
+class OCSPResponse
+{
+       NOCOPY(OCSPResponse)
+public:
+       /* only constructor, from DER encoded data */
+       OCSPResponse(
+               const CSSM_DATA &resp,
+               CFTimeInterval defaultTTL);             // default time-to-live in seconds
+               
+       ~OCSPResponse();
+       
+       /* 
+        * Info obtained during decode (which is don\ 1e immediately during constructor) 
+        */
+       SecAsn1OCSPResponseStatus       responseStatus();
+       const CSSM_DATA                         *nonce();                       /* NULL means not present */
+       CFAbsoluteTime                          producedAt();           /* should always work */
+       CSSM_RETURN                                     sigStatus();
+       uint32                                          numSignerCerts();
+       const CSSM_DATA                         *signerCert(uint32 dex);
+       
+       /* 
+        * Obtain a OCSPSingleResponse for a given CertID. 
+        */
+       OCSPSingleResponse                      *singleResponseFor(OCSPClientCertID &certID);
+       OCSPSingleResponse                      *singleResponseFor(const CSSM_DATA &matchCertID);
+       
+       CFAbsoluteTime                          expireTime()            { return mExpireTime; }
+
+       /*
+        * Access to decoded data.
+        */
+       const SecAsn1OCSPResponseData   &responseData()         { return mResponseData; }
+       const SecAsn1OCSPBasicResponse  &basicResponse()        { return mBasicResponse; }
+       const SecAsn1OCSPResponderID    &responderID()          { return mResponderId; }
+       SecAsn1OCSPResponderIDTag               responderIDTag()        { return mResponderIdTag; }
+
+       const CSSM_DATA                                 *encResponderName();
+       
+private:
+       bool                                            calculateValidity(CFTimeInterval defaultTTL);
+       
+       SecAsn1CoderRef                         mCoder;
+       CFAbsoluteTime                          mLatestNextUpdate;
+       CFAbsoluteTime                          mExpireTime;
+       CSSM_DATA                                       mEncResponderName;      // encoded ResponderId.byName, 
+                                                                                                       // if responder is in that format,
+                                                                                                       // lazily evaluated
+       /* 
+        * Fields we decode - all in mCoder's memory space 
+        */
+       SecAsn1OCSPResponse                     mTopResp;
+       SecAsn1OCSPBasicResponse        mBasicResponse;
+       SecAsn1OCSPResponseData         mResponseData;
+       SecAsn1OCSPResponderID          mResponderId;           // we have to decode
+       SecAsn1OCSPResponderIDTag       mResponderIdTag;        // IDs previous field
+       OCSPExtensions                          *mExtensions;
+};     
+#endif /* _OCSP_RESPONSE_H_ */
+