X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/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 index 00000000..5c0de2f6 --- /dev/null +++ b/Security/libsecurity_ocspd/common/ocspResponse.h @@ -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 +#include +#include +#include +#include + +/* 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 done 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_ */ +