2 * Copyright (c) 2000-2001,2011,2014 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 // Apple X.509 CRL-related session functions.
23 #include "AppleX509CLSession.h"
24 #include "clNssUtils.h"
25 #include "clNameUtils.h"
28 AppleX509CLSession::CrlDescribeFormat(
29 uint32
&NumberOfFields
,
30 CSSM_OID_PTR
&OidList
)
32 DecodedCrl::describeFormat(*this, NumberOfFields
, OidList
);
37 AppleX509CLSession::CrlGetAllFields(
39 uint32
&NumberOfCrlFields
,
40 CSSM_FIELD_PTR
&CrlFields
)
42 class DecodedCrl
decodedCrl(*this, Crl
);
43 decodedCrl
.getAllParsedCrlFields(NumberOfCrlFields
, CrlFields
);
48 AppleX509CLSession::CrlGetFirstFieldValue(
50 const CssmData
&CrlField
,
51 uint32
&NumberOfMatchedFields
,
54 NumberOfMatchedFields
= 0;
56 CssmAutoData
aData(*this);
58 DecodedCrl
*decodedCrl
= new DecodedCrl(*this, Crl
);
61 /* this returns false if field not there, throws on bad OID */
64 brtn
= decodedCrl
->getCrlFieldData(CrlField
,
75 return CSSM_INVALID_HANDLE
;
78 /* cook up a CLCachedCRL, stash it in cache */
79 CLCachedCRL
*cachedCrl
= new CLCachedCRL(*decodedCrl
);
80 cacheMap
.addEntry(*cachedCrl
, cachedCrl
->handle());
82 /* cook up a CLQuery, stash it */
83 CLQuery
*query
= new CLQuery(
89 queryMap
.addEntry(*query
, query
->handle());
91 /* success - copy field data to outgoing Value */
92 Value
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
));
93 *Value
= aData
.release();
94 NumberOfMatchedFields
= numMatches
;
95 return query
->handle();
100 AppleX509CLSession::CrlGetNextFieldValue(
101 CSSM_HANDLE ResultsHandle
,
102 CSSM_DATA_PTR
&Value
)
104 /* fetch & validate the query */
105 CLQuery
*query
= queryMap
.lookupEntry(ResultsHandle
);
107 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE
);
109 if(query
->queryType() != CLQ_CRL
) {
110 clErrorLog("CrlGetNextFieldValue: bad queryType (%d)",
111 (int)query
->queryType());
112 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE
);
114 if(query
->nextIndex() >= query
->numFields()) {
118 /* fetch the associated cached CRL */
119 CLCachedCRL
*cachedCrl
= lookupCachedCRL(query
->cachedObject());
121 CssmAutoData
aData(*this);
122 if(!cachedCrl
->crl().getCrlFieldData(query
->fieldId(),
129 /* success - copy field data to outgoing Value */
130 Value
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
));
131 *Value
= aData
.release();
132 query
->incrementIndex();
138 AppleX509CLSession::IsCertInCrl(
139 const CssmData
&Cert
,
141 CSSM_BOOL
&CertFound
)
144 * Decode the two entities. Note that doing it this way incurs
145 * the unnecessary (for our purposes) overhead of decoding
146 * extensions, but doing it this way is so spiffy that I can't
149 DecodedCert
decodedCert(*this, Cert
);
150 DecodedCrl
decodedCrl(*this, Crl
);
152 NSS_TBSCertificate
&tbsCert
= decodedCert
.mCert
.tbs
;
153 NSS_TBSCrl
&tbsCrl
= decodedCrl
.mCrl
.tbs
;
155 /* trivial case - empty CRL */
156 unsigned numCrlEntries
=
157 clNssArraySize((const void **)tbsCrl
.revokedCerts
);
158 if(numCrlEntries
== 0) {
159 clFieldLog("IsCertInCrl: empty CRL");
160 CertFound
= CSSM_FALSE
;
165 * Get normalized and encoded versions of issuer names.
166 * Since the decoded entities are local, we can normalize in place.
168 CssmAutoData
encCertIssuer(*this);
169 CssmAutoData
encCrlIssuer(*this);
171 /* snag a handy temp allocator */
172 SecNssCoder
&coder
= decodedCert
.coder();
173 CL_normalizeX509NameNSS(tbsCert
.issuer
, coder
);
174 PRErrorCode prtn
= SecNssEncodeItemOdata(&tbsCert
.issuer
,
175 kSecAsn1NameTemplate
, encCertIssuer
);
177 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);
180 CL_normalizeX509NameNSS(tbsCrl
.issuer
, coder
);
181 prtn
= SecNssEncodeItemOdata(&tbsCrl
.issuer
,
182 kSecAsn1NameTemplate
, encCrlIssuer
);
184 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR
);
188 clFieldLog("IsCertInCrl: normalize failure");
192 /* issuer names match? */
193 CertFound
= CSSM_FALSE
;
194 if(encCertIssuer
.get() != encCrlIssuer
.get()) {
195 clFieldLog("IsCertInCrl: issuer name mismatch");
199 /* is this cert's serial number in the CRL? */
200 CSSM_DATA
&certSerial
= tbsCert
.serialNumber
;
201 for(unsigned dex
=0; dex
<numCrlEntries
; dex
++) {
202 NSS_RevokedCert
*revokedCert
= tbsCrl
.revokedCerts
[dex
];
203 assert(revokedCert
!= NULL
);
204 CSSM_DATA
&revokedSerial
= revokedCert
->userCertificate
;
205 if(clCompareCssmData(&certSerial
, &revokedSerial
)) {
207 CertFound
= CSSM_TRUE
;
213 #pragma mark --- Cached ---
216 AppleX509CLSession::CrlCache(
218 CSSM_HANDLE
&CrlHandle
)
220 DecodedCrl
*decodedCrl
= new DecodedCrl(*this, Crl
);
222 /* cook up a CLCachedCRL, stash it in cache */
223 CLCachedCRL
*cachedCrl
= new CLCachedCRL(*decodedCrl
);
224 cacheMap
.addEntry(*cachedCrl
, cachedCrl
->handle());
225 CrlHandle
= cachedCrl
->handle();
229 * FIXME - CrlRecordIndex not supported, it'll require mods to
230 * the DecodedCrl::getCrlFieldData mechanism
233 AppleX509CLSession::CrlGetFirstCachedFieldValue(
234 CSSM_HANDLE CrlHandle
,
235 const CssmData
*CrlRecordIndex
,
236 const CssmData
&CrlField
,
237 uint32
&NumberOfMatchedFields
,
238 CSSM_DATA_PTR
&Value
)
240 if(CrlRecordIndex
!= NULL
) {
242 CssmError::throwMe(CSSMERR_CL_INVALID_CRL_INDEX
);
245 /* fetch the associated cached CRL */
246 CLCachedCRL
*cachedCrl
= lookupCachedCRL(CrlHandle
);
247 if(cachedCrl
== NULL
) {
248 CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE
);
251 CssmAutoData
aData(*this);
254 /* this returns false if field not there, throws on bad OID */
255 if(!cachedCrl
->crl().getCrlFieldData(CrlField
,
259 return CSSM_INVALID_HANDLE
;
262 /* cook up a CLQuery, stash it */
263 CLQuery
*query
= new CLQuery(
268 cachedCrl
->handle());
269 queryMap
.addEntry(*query
, query
->handle());
271 /* success - copy field data to outgoing Value */
272 Value
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
));
273 *Value
= aData
.release();
274 NumberOfMatchedFields
= numMatches
;
275 return query
->handle();
280 AppleX509CLSession::CrlGetNextCachedFieldValue(
281 CSSM_HANDLE ResultsHandle
,
282 CSSM_DATA_PTR
&Value
)
284 /* Identical to, so just call... */
285 return CrlGetNextFieldValue(ResultsHandle
, Value
);
290 AppleX509CLSession::IsCertInCachedCrl(
291 const CssmData
&Cert
,
292 CSSM_HANDLE CrlHandle
,
293 CSSM_BOOL
&CertFound
,
294 CssmData
&CrlRecordIndex
)
301 AppleX509CLSession::CrlAbortCache(
302 CSSM_HANDLE CrlHandle
)
304 /* fetch the associated cached CRL, remove from map, delete it */
305 CLCachedCRL
*cachedCrl
= lookupCachedCRL(CrlHandle
);
306 if(cachedCrl
== NULL
) {
307 CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE
);
309 cacheMap
.removeEntry(cachedCrl
->handle());
315 AppleX509CLSession::CrlAbortQuery(
316 CSSM_HANDLE ResultsHandle
)
318 /* fetch & validate the query */
319 CLQuery
*query
= queryMap
.lookupEntry(ResultsHandle
);
321 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE
);
323 if(query
->queryType() != CLQ_CRL
) {
324 clErrorLog("CrlAbortQuery: bad queryType (%d)", (int)query
->queryType());
325 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE
);
328 if(!query
->fromCache()) {
329 /* the associated cached CRL was created just for this query; dispose */
330 CLCachedCRL
*cachedCrl
= lookupCachedCRL(query
->cachedObject());
331 if(cachedCrl
== NULL
) {
332 /* should never happen */
333 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
335 cacheMap
.removeEntry(cachedCrl
->handle());
338 queryMap
.removeEntry(query
->handle());
342 #pragma mark --- Template ---
345 AppleX509CLSession::CrlCreateTemplate(
346 uint32 NumberOfFields
,
347 const CSSM_FIELD
*CrlTemplate
,
355 AppleX509CLSession::CrlSetFields(
356 uint32 NumberOfFields
,
357 const CSSM_FIELD
*CrlTemplate
,
358 const CssmData
&OldCrl
,
359 CssmData
&ModifiedCrl
)
366 AppleX509CLSession::CrlAddCert(
367 CSSM_CC_HANDLE CCHandle
,
368 const CssmData
&Cert
,
369 uint32 NumberOfFields
,
370 const CSSM_FIELD CrlEntryFields
[],
371 const CssmData
&OldCrl
,
379 AppleX509CLSession::CrlRemoveCert(
380 const CssmData
&Cert
,
381 const CssmData
&OldCrl
,
389 AppleX509CLSession::CrlGetAllCachedRecordFields(
390 CSSM_HANDLE CrlHandle
,
391 const CssmData
&CrlRecordIndex
,
392 uint32
&NumberOfFields
,
393 CSSM_FIELD_PTR
&CrlFields
)
399 * These are functionally identical to the corresponding
403 AppleX509CLSession::CrlVerifyWithKey(
404 CSSM_CC_HANDLE CCHandle
,
405 const CssmData
&CrlToBeVerified
)
407 CertVerifyWithKey(CCHandle
, CrlToBeVerified
);
412 AppleX509CLSession::CrlVerify(
413 CSSM_CC_HANDLE CCHandle
,
414 const CssmData
&CrlToBeVerified
,
415 const CssmData
*SignerCert
,
416 const CSSM_FIELD
*VerifyScope
,
419 CertVerify(CCHandle
, CrlToBeVerified
, SignerCert
, VerifyScope
,
424 AppleX509CLSession::CrlSign(
425 CSSM_CC_HANDLE CCHandle
,
426 const CssmData
&UnsignedCrl
,
427 const CSSM_FIELD
*SignScope
,