]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | /* | |
25 | * ocspResponse.h - OCSP Response class | |
26 | */ | |
27 | ||
28 | #ifndef _OCSP_RESPONSE_H_ | |
29 | #define _OCSP_RESPONSE_H_ | |
30 | ||
31 | #include <security_ocspd/ocspExtensions.h> | |
32 | #include <Security/ocspTemplates.h> | |
33 | #include <Security/certextensions.h> | |
34 | #include <Security/SecAsn1Coder.h> | |
35 | #include <CoreFoundation/CoreFoundation.h> | |
36 | ||
37 | /* used to indicate "I don't know the CRLReason" */ | |
38 | #define CrlReason_NONE ((CE_CrlReason)-1) | |
39 | ||
40 | /* | |
41 | * CertIDs can be represented differently by two peers even though they refer to | |
42 | * the same cert. Client can use SHA1 hash and server can use MD5, for example. | |
43 | * So all of our code which creates a CertID based on known, existing subject and | |
44 | * issuer certs uses one of these "smart" certIDs which can encode itself and also | |
45 | * compare against any form of existing SecAsn1OCSPCertID. | |
46 | */ | |
47 | class OCSPClientCertID | |
48 | { | |
49 | NOCOPY(OCSPClientCertID); | |
50 | public: | |
51 | /* | |
52 | * Basic constructor given issuer's public key and name, and subject's | |
53 | * serial number. | |
54 | */ | |
55 | OCSPClientCertID( | |
56 | const CSSM_DATA &issuerName, | |
57 | const CSSM_DATA &issuerPubKey, | |
58 | const CSSM_DATA &subjectSerial); | |
59 | ||
60 | ~OCSPClientCertID(); | |
61 | ||
62 | /* | |
63 | * DER encode. | |
64 | */ | |
65 | const CSSM_DATA *encode(); | |
66 | ||
67 | /* | |
68 | * Does this object refer to the same cert as specified SecAsn1OCSPCertID? | |
69 | * This is the main purpose of this class's existence; this function works | |
70 | * even if specified SecAsn1OCSPCertID uses a different hash algorithm | |
71 | * than we do, since we keep copies of our basic components. | |
72 | * | |
73 | * Returns true if compare successful. | |
74 | */ | |
75 | bool compareToExist( | |
76 | const SecAsn1OCSPCertID &exist); | |
77 | ||
78 | /* | |
79 | * Convenience function, like compareToExist, with a raw encoded CertID. | |
80 | */ | |
81 | bool compareToExist( | |
82 | const CSSM_DATA &exist); | |
83 | ||
84 | private: | |
85 | CSSM_DATA mIssuerName; | |
86 | CSSM_DATA mIssuerPubKey; | |
87 | CSSM_DATA mSubjectSerial; | |
88 | CSSM_DATA mEncoded; | |
89 | }; | |
90 | ||
91 | /* | |
92 | * Object representing one SecAsn1OCSPSingleResponse, i.e., the portion of | |
93 | * an OCSP response associated with a single CertID. These are created and | |
94 | * vended solely by an OCSPResponse object. The client which gets them from | |
95 | * an OCSPResponse (via singleResponse()) must delete the object when finished | |
96 | * with it. | |
97 | */ | |
98 | class OCSPSingleResponse | |
99 | { | |
100 | NOCOPY(OCSPSingleResponse); | |
101 | public: | |
102 | /* only OCSPResponse creates these */ | |
103 | ~OCSPSingleResponse(); | |
104 | friend class OCSPResponse; | |
105 | protected: | |
106 | ||
107 | OCSPSingleResponse( | |
108 | SecAsn1OCSPSingleResponse *resp); | |
109 | public: | |
110 | SecAsn1OCSPCertStatusTag certStatus() { return mCertStatus; } | |
111 | CFAbsoluteTime thisUpdate() { return mThisUpdate; } | |
112 | CFAbsoluteTime nextUpdate() { return mNextUpdate; } | |
113 | CFAbsoluteTime revokedTime() { return mRevokedTime; } | |
114 | CE_CrlReason crlReason() { return mCrlReason; } | |
115 | ||
116 | /* Extension accessors - all are optional */ | |
117 | ||
118 | /* CRL Reference */ | |
119 | const CSSM_DATA *crlUrl(); | |
120 | const CSSM_DATA *crlNum(); | |
121 | CFAbsoluteTime crlTime(); /* may be NULL_TIME */ | |
122 | ||
123 | /* archive cutoff */ | |
124 | CFAbsoluteTime archiveCutoff(); | |
125 | ||
126 | /* service locator not implemented yet */ | |
127 | private: | |
128 | SecAsn1CoderRef mCoder; | |
129 | SecAsn1OCSPCertStatusTag mCertStatus; | |
130 | CFAbsoluteTime mThisUpdate; | |
131 | CFAbsoluteTime mNextUpdate; /* may be NULL_TIME */ | |
132 | CFAbsoluteTime mRevokedTime; /* != NULL_TIME for CS_Revoked */ | |
133 | CE_CrlReason mCrlReason; | |
134 | OCSPExtensions *mExtensions; | |
135 | }; | |
136 | ||
137 | /* | |
138 | * OCSPResponse maintains its own temporal validity status based on the values of | |
139 | * all of the enclosed SingleResponses' thisUpdate and (optional) nextUpdate | |
140 | * fields, in addition to a default time-to-live (TTL) value passed to | |
141 | * OCSPResponse's constructor. | |
142 | * | |
143 | * First, all of the thisUpdate fields are checked during OCSPResponse's constructor. | |
144 | * if any of these are later than the current time, the entire response is considered | |
145 | * invalid and the constructor throws a CssmError(CSSMERR_APPLETP_OCSP_BAD_RESPONSE). | |
146 | * Subsequent to construction, all thisUpdate fields are ignored. | |
147 | * | |
148 | * The NextUpdate times are handled as follows. | |
149 | * | |
150 | * 1. An OCSPResponse's latestNextUpdate is defined as the latest of all of the | |
151 | * nextUpdate fields in its SingleResponses. This is evaluated during construction. | |
152 | * | |
153 | * 2. An OCSPResponse's latestNextUpdate is NULL_TIME if none of its SingleResponses | |
154 | * contain any nextUpdate (this field is in fact optional). | |
155 | * | |
156 | * 3. The caller of OCSPResponse's constructor passes in a default time-to-live | |
157 | * (TTL) in seconds; call this defaultTTL. Call the time at which the | |
158 | * constructor is called, PLUS defaultTTL, "defaultExpire". | |
159 | * | |
160 | * -- If the OCSPResponse's latestNextUpdate is NULL_TIME then expireTime() returns | |
161 | * defaultExpire. | |
162 | * | |
163 | * -- Otherwise, expireTime() returns the lesser of (latestNextUpdate, | |
164 | * defaultExpire). | |
165 | * | |
166 | * Note that this mechanism is used by both the TP's in-core cache and ocspd's | |
167 | * on-disk cache; the two have different default TTLs values but the mechanism | |
168 | * for calcuating expireTime() is identical. | |
169 | */ | |
170 | class OCSPResponse | |
171 | { | |
172 | NOCOPY(OCSPResponse) | |
173 | public: | |
174 | /* only constructor, from DER encoded data */ | |
175 | OCSPResponse( | |
176 | const CSSM_DATA &resp, | |
177 | CFTimeInterval defaultTTL); // default time-to-live in seconds | |
178 | ||
179 | ~OCSPResponse(); | |
180 | ||
181 | /* | |
182 | * Info obtained during decode (which is don\ 1e immediately during constructor) | |
183 | */ | |
184 | SecAsn1OCSPResponseStatus responseStatus(); | |
185 | const CSSM_DATA *nonce(); /* NULL means not present */ | |
186 | CFAbsoluteTime producedAt(); /* should always work */ | |
187 | CSSM_RETURN sigStatus(); | |
188 | uint32 numSignerCerts(); | |
189 | const CSSM_DATA *signerCert(uint32 dex); | |
190 | ||
191 | /* | |
192 | * Obtain a OCSPSingleResponse for a given CertID. | |
193 | */ | |
194 | OCSPSingleResponse *singleResponseFor(OCSPClientCertID &certID); | |
195 | OCSPSingleResponse *singleResponseFor(const CSSM_DATA &matchCertID); | |
196 | ||
197 | CFAbsoluteTime expireTime() { return mExpireTime; } | |
198 | ||
199 | /* | |
200 | * Access to decoded data. | |
201 | */ | |
202 | const SecAsn1OCSPResponseData &responseData() { return mResponseData; } | |
203 | const SecAsn1OCSPBasicResponse &basicResponse() { return mBasicResponse; } | |
204 | const SecAsn1OCSPResponderID &responderID() { return mResponderId; } | |
205 | SecAsn1OCSPResponderIDTag responderIDTag() { return mResponderIdTag; } | |
206 | ||
207 | const CSSM_DATA *encResponderName(); | |
208 | ||
209 | private: | |
210 | bool calculateValidity(CFTimeInterval defaultTTL); | |
211 | ||
212 | SecAsn1CoderRef mCoder; | |
213 | CFAbsoluteTime mLatestNextUpdate; | |
214 | CFAbsoluteTime mExpireTime; | |
215 | CSSM_DATA mEncResponderName; // encoded ResponderId.byName, | |
216 | // if responder is in that format, | |
217 | // lazily evaluated | |
218 | /* | |
219 | * Fields we decode - all in mCoder's memory space | |
220 | */ | |
221 | SecAsn1OCSPResponse mTopResp; | |
222 | SecAsn1OCSPBasicResponse mBasicResponse; | |
223 | SecAsn1OCSPResponseData mResponseData; | |
224 | SecAsn1OCSPResponderID mResponderId; // we have to decode | |
225 | SecAsn1OCSPResponderIDTag mResponderIdTag; // IDs previous field | |
226 | OCSPExtensions *mExtensions; | |
227 | }; | |
228 | #endif /* _OCSP_RESPONSE_H_ */ | |
229 |