]> git.saurik.com Git - apple/security.git/blob - AppleX509CL/CrlFields.cpp
8ae54a7e7fef111ca73dd582286a6b18d2476561
[apple/security.git] / AppleX509CL / CrlFields.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 /*
20 * CrlFields.cpp - convert between NSS-based NSS_Crl components and CDSA-style
21 * fields. A major component of DecodedCrl.
22 *
23 * Created 8/29/2002 by Doug Mitchell.
24 * Copyright (c) 2002 by Apple Computer.
25 */
26
27 #include "DecodedCrl.h"
28 #include <Security/debugging.h>
29 #include "cldebugging.h"
30 #include "CLCrlExtensions.h"
31 #include "CLCertExtensions.h"
32 #include "CLFieldsCommon.h"
33 #include "clNssUtils.h"
34 #include "clNameUtils.h"
35 #include <Security/utilities.h>
36 #include <Security/oidscrl.h>
37 #include <Security/oidscert.h>
38 #include <Security/cssmerr.h>
39 #include <Security/x509defs.h>
40
41 static void CL_freeCssmExtensions(
42 CSSM_X509_EXTENSIONS &extens,
43 CssmAllocator &alloc);
44
45 /***
46 *** Version
47 *** Format = DER-encoded int (max of four bytes in this case)
48 ***/
49 static bool getField_Version (
50 DecodedItem &item,
51 unsigned index, // which occurrence (0 = first)
52 uint32 &numFields, // RETURNED
53 CssmOwnedData &fieldValue) // RETURNED
54 {
55 const DecodedCrl &crl = dynamic_cast<const DecodedCrl &>(item);
56 const CSSM_DATA &vers = crl.mCrl.tbs.version;
57 if(!tbsGetCheck(vers.Data, index)) {
58 /* not present, optional */
59 return false;
60 }
61 fieldValue.copy(vers.Data, vers.Length);
62 numFields = 1;
63 return true;
64 }
65
66 static void setField_Version (
67 DecodedItem &item,
68 const CssmData &fieldValue)
69 {
70 DecodedCrl &crl = dynamic_cast<DecodedCrl &>(item);
71 CSSM_DATA &vers = crl.mCrl.tbs.version;
72 tbsSetCheck(vers.Data, fieldValue, 0, "version");
73 crl.coder().allocCopyItem(fieldValue, vers);
74 }
75
76 /*** issuer
77 *** Format = CSSM_X509_NAME
78 *** class Name from sm_x501if
79 ***/
80 static bool getField_Issuer (
81 DecodedItem &item,
82 unsigned index, // which occurrence (0 = first)
83 uint32 &numFields, // RETURNED
84 CssmOwnedData &fieldValue) // RETURNED
85 {
86 if(index != 0) {
87 return false;
88 }
89
90 bool brtn;
91
92 const DecodedCrl &crl = dynamic_cast<const DecodedCrl &>(item);
93 try {
94 brtn = getField_RDN_NSS(crl.mCrl.tbs.issuer, fieldValue);
95 if(brtn) {
96 numFields = 1;
97 }
98 }
99 catch (...) {
100 freeField_RDN(fieldValue);
101 throw;
102 }
103 return brtn;
104 }
105
106 static void setField_Issuer (
107 DecodedItem &item,
108 const CssmData &fieldValue)
109 {
110 DecodedCrl &crl = dynamic_cast<DecodedCrl &>(item);
111 const CSSM_X509_NAME *cssmName = (const CSSM_X509_NAME *)fieldValue.Data;
112 NSS_Name &nssName = crl.mCrl.tbs.issuer;
113 tbsSetCheck(nssName.rdns, fieldValue, sizeof(CSSM_X509_NAME),
114 "IssuerName");
115 CL_cssmNameToNss(*cssmName, nssName, crl.coder());
116 }
117
118 /***
119 *** This/Next update
120 *** Format: CSSM_X509_TIME
121 ***/
122 static bool getField_ThisUpdate (
123 DecodedItem &item,
124 unsigned index, // which occurrence (0 = first)
125 uint32 &numFields, // RETURNED
126 CssmOwnedData &fieldValue) // RETURNED
127 {
128 const DecodedCrl &crl = dynamic_cast<const DecodedCrl &>(item);
129 const NSS_Time &srcTime = crl.mCrl.tbs.thisUpdate;
130 return getField_TimeNSS(srcTime, index, numFields, fieldValue);
131 }
132
133 static void setField_ThisUpdate (
134 DecodedItem &item,
135 const CssmData &fieldValue)
136 {
137 DecodedCrl &crl = dynamic_cast<DecodedCrl &>(item);
138 NSS_Time &dstTime = crl.mCrl.tbs.thisUpdate;
139 tbsSetCheck(dstTime.item.Data, fieldValue,
140 sizeof(CSSM_X509_TIME), "NotBefore");
141 setField_TimeNSS(fieldValue, dstTime, crl.coder());
142 }
143
144 static bool getField_NextUpdate (
145 DecodedItem &item,
146 unsigned index, // which occurrence (0 = first)
147 uint32 &numFields, // RETURNED
148 CssmOwnedData &fieldValue) // RETURNED
149 {
150 const DecodedCrl &crl = dynamic_cast<const DecodedCrl &>(item);
151 const NSS_Time &srcTime = crl.mCrl.tbs.nextUpdate;
152 return getField_TimeNSS(srcTime, index, numFields, fieldValue);
153 }
154
155 static void setField_NextUpdate (
156 DecodedItem &item,
157 const CssmData &fieldValue)
158 {
159 DecodedCrl &crl = dynamic_cast<DecodedCrl &>(item);
160 NSS_Time &dstTime = crl.mCrl.tbs.nextUpdate;
161 tbsSetCheck(dstTime.item.Data, fieldValue,
162 sizeof(CSSM_X509_TIME), "NotBefore");
163 setField_TimeNSS(fieldValue, dstTime, crl.coder());
164 }
165
166 /***
167 *** Issuer Name (normalized and encoded version)
168 *** Format = CSSM_DATA containing the DER encoding of the normalized name
169 ***/
170 static bool getFieldIssuerNorm(
171 DecodedItem &item,
172 unsigned index, // which occurrence (0 = first)
173 uint32 &numFields, // RETURNED
174 CssmOwnedData &fieldValue) // RETURNED
175 {
176 if(index != 0) {
177 return false;
178 }
179 const DecodedCrl &crl = dynamic_cast<const DecodedCrl &>(item);
180 return getField_normRDN_NSS(crl.mCrl.tbs.derIssuer, numFields,
181 fieldValue);
182 }
183
184 /***
185 *** TBS AlgId
186 *** Format = CSSM_X509_ALGORITHM_IDENTIFIER
187 ***/
188 static bool getField_CrlTbsAlgId (
189 DecodedItem &item,
190 unsigned index, // which occurrence (0 = first)
191 uint32 &numFields, // RETURNED
192 CssmOwnedData &fieldValue) // RETURNED
193 {
194 const DecodedCrl &crl = dynamic_cast<const DecodedCrl &>(item);
195 const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId =
196 crl.mCrl.signatureAlgorithm;
197 if(!tbsGetCheck(srcAlgId.algorithm.Data, index)) {
198 return false;
199 }
200 getField_AlgIdNSS(srcAlgId, fieldValue);
201 numFields = 1;
202 return true;
203 }
204
205 /*
206 * Support for entries in revocation list
207 */
208 static void nssRevokedEntryToCssm(
209 NSS_RevokedCert &nssEntry,
210 CSSM_X509_REVOKED_CERT_ENTRY &cssmEntry,
211 CssmAllocator &alloc)
212 {
213 clAllocCopyData(alloc, nssEntry.userCertificate, cssmEntry.certificateSerialNumber);
214 CL_nssTimeToCssm(nssEntry.revocationDate, cssmEntry.revocationDate, alloc);
215
216 /* CSSM_X509_EXTENSIONS extensions */
217 NSS_CertExtension **nssExtens = nssEntry.extensions;
218 if(nssExtens == NULL) {
219 /* done */
220 return;
221 }
222
223 /*
224 * First we have to decode the NSS-style Extensions into a
225 * DecodedExtensions object. For cert- and CRL-wide extensions, this
226 * is done at the construction of Decoded{Cert,Crl}. However for
227 * per-CRL-entry entensions, this is (currently) the only place
228 * this decoding is done.
229 */
230 SecNssCoder coder;
231 DecodedExtensions decodedExtens(coder, alloc);
232 decodedExtens.decodeFromNss(nssExtens);
233
234 /* convert to CDSA style */
235 decodedExtens.convertToCdsa(cssmEntry.extensions, alloc);
236 }
237
238 static void freeCssmEntry(
239 CSSM_X509_REVOKED_CERT_ENTRY_PTR cssmEntry,
240 CssmAllocator &alloc)
241 {
242 if(cssmEntry == NULL) {
243 return;
244 }
245 if(cssmEntry->certificateSerialNumber.Data) {
246 alloc.free(cssmEntry->certificateSerialNumber.Data);
247 cssmEntry->certificateSerialNumber.Data = NULL;
248 cssmEntry->certificateSerialNumber.Length = 0;
249 }
250 CL_freeCssmTime(&cssmEntry->revocationDate, alloc);
251
252 /* CSSM_X509_EXTENSIONS extensions */
253 CL_freeCssmExtensions(cssmEntry->extensions, alloc);
254
255 memset(cssmEntry, 0, sizeof(CSSM_X509_REVOKED_CERT_ENTRY));
256 }
257
258 static void nssRevokedListToCssm(
259 NSS_RevokedCert **nssList, // may be NULL
260 CSSM_X509_REVOKED_CERT_LIST_PTR cssmList,
261 CssmAllocator &alloc)
262 {
263 unsigned numEntries = clNssArraySize((const void **)nssList);
264 cssmList->numberOfRevokedCertEntries = numEntries;
265 if(numEntries == 0) {
266 cssmList->revokedCertEntry = NULL;
267 return;
268 }
269 cssmList->revokedCertEntry = (CSSM_X509_REVOKED_CERT_ENTRY_PTR)alloc.malloc(
270 sizeof(CSSM_X509_REVOKED_CERT_ENTRY) * numEntries);
271 memset(cssmList->revokedCertEntry, 0,
272 sizeof(CSSM_X509_REVOKED_CERT_ENTRY) * numEntries);
273 for(unsigned dex=0; dex<numEntries; dex++) {
274 NSS_RevokedCert *nssEntry = nssList[dex];
275 assert(nssEntry != NULL);
276 CSSM_X509_REVOKED_CERT_ENTRY_PTR cssmEntry =
277 &cssmList->revokedCertEntry[dex];
278 nssRevokedEntryToCssm(*nssEntry, *cssmEntry, alloc);
279 }
280 }
281
282
283 static void freeCssmRevokedList(
284 CSSM_X509_REVOKED_CERT_LIST_PTR cssmList,
285 CssmAllocator &alloc)
286 {
287 if(cssmList == NULL) {
288 return;
289 }
290 for(unsigned dex=0; dex<cssmList->numberOfRevokedCertEntries; dex++) {
291 CSSM_X509_REVOKED_CERT_ENTRY_PTR cssmEntry =
292 &cssmList->revokedCertEntry[dex];
293 freeCssmEntry(cssmEntry, alloc);
294 }
295 if(cssmList->revokedCertEntry) {
296 alloc.free(cssmList->revokedCertEntry);
297 }
298 memset(cssmList, 0, sizeof(CSSM_X509_REVOKED_CERT_LIST));
299 }
300
301 /***
302 *** SignedCRL
303 *** Format: CSSM_X509_SIGNED_CRL (the whole enchilada, parsed)
304 ***/
305 static bool getField_SignedCrl (
306 DecodedItem &item,
307 unsigned index, // which occurrence (0 = first)
308 uint32 &numFields, // RETURNED
309 CssmOwnedData &fieldValue) // RETURNED
310 {
311 CssmAllocator &alloc = fieldValue.allocator;
312
313 const DecodedCrl &nssCrl = dynamic_cast<const DecodedCrl &>(item);
314 const NSS_TBSCrl &nssTbs = nssCrl.mCrl.tbs;
315 fieldValue.malloc(sizeof(CSSM_X509_SIGNED_CRL));
316 CSSM_X509_SIGNED_CRL &cssmCrl = *((CSSM_X509_SIGNED_CRL *)fieldValue.data());
317
318 memset(&cssmCrl, 0, sizeof(CSSM_X509_SIGNED_CRL));
319 CSSM_X509_TBS_CERTLIST &cssmTbs = cssmCrl.tbsCertList;
320
321 /* version */
322 clAllocCopyData(alloc, nssTbs.version, cssmTbs.version);
323
324 /* CSSM_X509_ALGORITHM_IDENTIFIER signature - in TBS and CRL */
325 CL_copyAlgId(nssTbs.signature, cssmTbs.signature, alloc);
326 CL_copyAlgId(nssCrl.mCrl.signatureAlgorithm,
327 cssmCrl.signature.algorithmIdentifier, alloc);
328
329 /* CSSM_X509_NAME issuer */
330 CL_nssNameToCssm(nssTbs.issuer, cssmTbs.issuer, alloc);
331
332 /* CSSM_X509_TIME thisUpdate, nextUpdate */
333 CL_nssTimeToCssm(nssTbs.thisUpdate, cssmTbs.thisUpdate, alloc);
334 CL_nssTimeToCssm(nssTbs.nextUpdate, cssmTbs.nextUpdate, alloc);
335
336 /* CSSM_X509_REVOKED_CERT_LIST_PTR revokedCertificates */
337 if(nssTbs.revokedCerts != NULL) {
338 cssmTbs.revokedCertificates = (CSSM_X509_REVOKED_CERT_LIST_PTR)
339 alloc.malloc(sizeof(CSSM_X509_REVOKED_CERT_LIST));
340 memset(cssmTbs.revokedCertificates, 0, sizeof(CSSM_X509_REVOKED_CERT_LIST));
341 nssRevokedListToCssm(nssTbs.revokedCerts,
342 cssmTbs.revokedCertificates, alloc);
343 }
344
345 /* CSSM_X509_EXTENSIONS extensions */
346 const DecodedExtensions &decodedExtens = nssCrl.decodedExtens();
347 decodedExtens.convertToCdsa(cssmTbs.extensions, alloc);
348
349 /* raw signature - stored in bits - note signature.algId set above */
350 CSSM_DATA nssSig = nssCrl.mCrl.signature;
351 nssSig.Length = (nssSig.Length + 7) / 8;
352 clAllocCopyData(alloc, nssSig, cssmCrl.signature.encrypted);
353 numFields = 1;
354 return true;
355 }
356
357 static void setField_SignedCrl (
358 DecodedItem &item,
359 const CssmData &fieldValue)
360 {
361 /* TBD - writing CRLs not supported now */
362 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
363 }
364
365 void freeField_SignedCrl (
366 CssmOwnedData &fieldValue)
367 {
368 CSSM_X509_SIGNED_CRL *cssmCrl =
369 (CSSM_X509_SIGNED_CRL *)fieldValue.data();
370
371 if(cssmCrl == NULL) {
372 return;
373 }
374 if(fieldValue.length() != sizeof(CSSM_X509_SIGNED_CRL)) {
375 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
376 }
377 CssmAllocator &alloc = fieldValue.allocator;
378 CSSM_X509_TBS_CERTLIST_PTR cssmTbs = &cssmCrl->tbsCertList;
379 if(cssmTbs == NULL) {
380 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
381 }
382
383 /* run down the fields */
384 if(cssmTbs->version.Data) {
385 alloc.free(cssmTbs->version.Data);
386 }
387
388 /* CSSM_X509_ALGORITHM_IDENTIFIER signature - in TBS and CRL */
389 CL_freeCssmAlgId(&cssmTbs->signature, alloc);
390 CL_freeCssmAlgId(&cssmCrl->signature.algorithmIdentifier, alloc);
391
392 /* issuer, thisUpdate, nextUpdate */
393 CL_freeX509Name(&cssmTbs->issuer, alloc);
394 CL_freeCssmTime(&cssmTbs->thisUpdate, alloc);
395 CL_freeCssmTime(&cssmTbs->nextUpdate, alloc);
396
397 /* CSSM_X509_REVOKED_CERT_LIST_PTR revokedCertificates */
398 freeCssmRevokedList(cssmTbs->revokedCertificates, alloc);
399 alloc.free(cssmTbs->revokedCertificates);
400
401 /* CSSM_X509_EXTENSIONS extensions */
402 CL_freeCssmExtensions(cssmTbs->extensions, alloc);
403
404 /* raw signature - note signature.algId freed above */
405 alloc.free(cssmCrl->signature.encrypted.Data);
406
407 memset(cssmCrl, 0, sizeof(CSSM_X509_SIGNED_CRL));
408 }
409
410 /*
411 * Table to map OID to {get,set,free}field
412 */
413 typedef struct {
414 const CSSM_OID *fieldId;
415 getItemFieldFcn *getFcn;
416 setItemFieldFcn *setFcn;
417 freeFieldFcn *freeFcn; // OPTIONAL - NULL means just free the
418 // top-level data
419 } oidToFieldFuncs;
420
421
422 static const oidToFieldFuncs crlFieldTable[] = {
423 /* this first one, which returns everything in a parsed format,
424 * is intended to be normally the only field used */
425 { &CSSMOID_X509V2CRLSignedCrlCStruct,
426 &getField_SignedCrl, &setField_SignedCrl, &freeField_SignedCrl },
427 { &CSSMOID_X509V2CRLVersion,
428 &getField_Version, &setField_Version, NULL },
429 { &CSSMOID_X509V1CRLIssuerNameCStruct,
430 &getField_Issuer, &setField_Issuer, &freeField_RDN },
431 { &CSSMOID_X509V1CRLThisUpdate,
432 &getField_ThisUpdate, &setField_ThisUpdate, &freeField_Time },
433 { &CSSMOID_X509V1CRLNextUpdate,
434 &getField_NextUpdate, &setField_NextUpdate, &freeField_Time },
435 { &CSSMOID_X509V1IssuerName,
436 getFieldIssuerNorm, &setField_ReadOnly, NULL },
437 { &CSSMOID_X509V1SignatureAlgorithmTBS,
438 &getField_CrlTbsAlgId, &setField_ReadOnly, &freeField_AlgId },
439 // ...etc..
440 /*
441 * Extensions, implemented in CrlExtensions.cpp
442 * When adding new ones, also add to:
443 * -- clOidToNssInfo() in CLFieldsCommon.cpp
444 * -- get/set/free functions in CrlExtensions.{cpp,h}
445 * -- DecodedExten::parse in DecodedExtensions.cpp
446 */
447 { &CSSMOID_CrlNumber,
448 &getFieldCrlNumber, &setFieldCrlNumber, freeFieldSimpleExtension },
449 { &CSSMOID_DeltaCrlIndicator,
450 &getFieldDeltaCrl, &setFieldCrlNumber, freeFieldSimpleExtension },
451 { &CSSMOID_CertIssuer, // get/set not implemented
452 &getField_Unimplemented, &setField_ReadOnly,
453 &freeFieldSubjIssuerAltName},
454 { &CSSMOID_CrlReason, // get/set not implemented
455 &getField_Unimplemented, &setField_ReadOnly,
456 freeFieldSimpleExtension},
457 { &CSSMOID_IssuingDistributionPoint, // get/set not implemented
458 &getField_Unimplemented, &setField_ReadOnly,
459 &freeFieldIssuingDistPoint},
460 { &CSSMOID_HoldInstructionCode, // get/set not implemented
461 &getField_Unimplemented, &setField_ReadOnly,
462 &freeFieldOidOrData},
463 { &CSSMOID_InvalidityDate, // get/set not implemented
464 &getField_Unimplemented, &setField_ReadOnly,
465 &freeFieldOidOrData},
466
467 /* in common with CertExtensions */
468 { &CSSMOID_AuthorityKeyIdentifier, &getFieldAuthorityKeyId,
469 &setFieldAuthorityKeyId, &freeFieldAuthorityKeyId } ,
470 { &CSSMOID_X509V3CertificateExtensionCStruct, &getFieldUnknownExt,
471 &setFieldUnknownExt, &freeFieldUnknownExt },
472 { &CSSMOID_SubjectAltName, &getFieldSubjAltName,
473 &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } ,
474 { &CSSMOID_IssuerAltName, &getFieldIssuerAltName,
475 &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } ,
476 // etc..
477 };
478
479 #define NUM_KNOWN_FIELDS (sizeof(crlFieldTable) / sizeof(oidToFieldFuncs))
480 #define NUM_STD_CRL_FIELDS 2 /* TBD not including extensions */
481
482 /* map an OID to an oidToFieldFuncs */
483 static const oidToFieldFuncs *oidToFields(
484 const CssmOid &fieldId)
485 {
486 const oidToFieldFuncs *fieldTable = crlFieldTable;
487 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) {
488 if(fieldId == CssmData::overlay(*fieldTable->fieldId)) {
489 return fieldTable;
490 }
491 fieldTable++;
492 }
493 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
494 }
495
496 /*
497 * Common routine to free OID-specific field data. Used in the
498 * public DecodedCrl::freeCrlFieldData and when freeing
499 * extensions in a CSSM_X509_TBS_CERTLIST.
500 */
501 static void CL_freeCrlFieldData(
502 const CssmOid &fieldId,
503 CssmOwnedData &fieldValue,
504 bool reset = true)
505 {
506 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) {
507 CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER);
508 }
509 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
510 if(fieldFuncs->freeFcn != NULL) {
511 /* optional - simple cases handled below */
512 fieldFuncs->freeFcn(fieldValue);
513 }
514 if(reset) {
515 fieldValue.reset();
516 fieldValue.release();
517 }
518 }
519
520 /*
521 * Common routime to free a CSSM_X509_EXTENSIONS. Used to free
522 * CSSM_X509_TBS_CERTLIST.extensions and
523 * CSSM_X509_REVOKED_CERT_ENTRY.extensions.
524 * We just cook up a CssmOid and a CssmOwnedData for each extension
525 * and pass to CL_freeCrlFieldData().
526 */
527 static void CL_freeCssmExtensions(
528 CSSM_X509_EXTENSIONS &extens,
529 CssmAllocator &alloc)
530 {
531 for(uint32 dex=0; dex<extens.numberOfExtensions; dex++) {
532 CSSM_X509_EXTENSION_PTR exten = &extens.extensions[dex];
533 const CSSM_OID *fieldOid;
534
535 /*
536 * The field OID is either the same as the extension's OID (if we parsed
537 * it) or CSSMOID_X509V3CertificateExtensionCStruct (if we didn't).
538 */
539 switch(exten->format) {
540 case CSSM_X509_DATAFORMAT_ENCODED:
541 fieldOid = &CSSMOID_X509V3CertificateExtensionCStruct;
542 break;
543 case CSSM_X509_DATAFORMAT_PARSED:
544 case CSSM_X509_DATAFORMAT_PAIR:
545 fieldOid = &exten->extnId;
546 break;
547 default:
548 clErrorLog("CL_freeCssmExtensions: bad exten->format (%d)",
549 (int)exten->format);
550 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
551 }
552
553 const CssmOid &fieldId = CssmOid::overlay(*fieldOid);
554 CssmData cData((uint8 *)exten, sizeof(CSSM_X509_EXTENSION));
555 CssmRemoteData fieldValue(alloc, cData);
556 CL_freeCrlFieldData(fieldId, fieldValue, false);
557 fieldValue.release(); // but no free (via reset() */
558 }
559 alloc.free(extens.extensions);
560 memset(&extens, 0, sizeof(CSSM_X509_EXTENSIONS));
561 }
562
563
564
565 /***
566 *** Public functions
567 ***/
568
569 /*
570 * Obtain the index'th occurrence of field specified by fieldId in specified cert.
571 * Format of the returned field depends on fieldId.
572 * Returns total number of fieldId fields in the cert if index is 0.
573 * FieldValue assumed to be empty on entry.
574 * Returns true if specified field was found, else returns false.
575 */
576 bool DecodedCrl::getCrlFieldData(
577 const CssmOid &fieldId, // which field
578 unsigned index, // which occurrence (0 = first)
579 uint32 &numFields, // RETURNED
580 CssmOwnedData &fieldValue) // RETURNED
581 {
582 switch(mState) {
583 case IS_Empty:
584 case IS_Building:
585 clErrorLog("DecodedCrl::getCrlField: can't parse undecoded CRL!");
586 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
587 case IS_DecodedAll:
588 case IS_DecodedTBS:
589 break;
590 }
591 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
592 return fieldFuncs->getFcn(*this, index, numFields, fieldValue);
593 }
594
595 /*
596 * Set the field specified by fieldId in the specified Cert.
597 * Note no index - individual field routines either append (for extensions)
598 * or if field already set ::throwMe(for all others)
599 */
600 void DecodedCrl::setCrlField(
601 const CssmOid &fieldId, // which field
602 const CssmData &fieldValue)
603 {
604 switch(mState) {
605 case IS_Empty: // first time thru
606 mState = IS_Building;
607 break;
608 case IS_Building: // subsequent passes
609 break;
610 case IS_DecodedAll:
611 case IS_DecodedTBS:
612 clErrorLog("DecodedCrl::setCrlField: can't build on a decoded CRL!");
613 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
614 }
615 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) {
616 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
617 }
618 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
619 const CssmData &value = CssmData::overlay(fieldValue);
620 fieldFuncs->setFcn(*this, value);
621 }
622
623 /*
624 * Free the fieldId-specific data referred to by fieldValue->Data.
625 * No state from DecodedCrl needed; use the routine shared with
626 * CL_freeCssmExtensions().
627 */
628 void DecodedCrl::freeCrlFieldData(
629 const CssmOid &fieldId,
630 CssmOwnedData &fieldValue)
631 {
632 CL_freeCrlFieldData(fieldId, fieldValue);
633 }
634
635
636 /*
637 * Common means to get all fields from a decoded CRL. Used in
638 * CrlGetAllTemplateFields and CrlGetAllFields.
639 */
640 void DecodedCrl::getAllParsedCrlFields(
641 uint32 &NumberOfFields, // RETURNED
642 CSSM_FIELD_PTR &CrlFields) // RETURNED
643 {
644 /* this is the max - some might be missing */
645 uint32 maxFields = NUM_STD_CRL_FIELDS + mDecodedExtensions.numExtensions();
646 CSSM_FIELD_PTR outFields = (CSSM_FIELD_PTR)mAlloc.malloc(
647 maxFields * sizeof(CSSM_FIELD));
648
649 /*
650 * We'll be copying oids and values for fields we find into
651 * outFields; current number of valid fields found in numOutFields.
652 */
653 memset(outFields, 0, maxFields * sizeof(CSSM_FIELD));
654 uint32 numOutFields = 0;
655 CSSM_FIELD_PTR currOutField;
656 uint32 currOidDex;
657 const CSSM_OID *currOid;
658 CssmAutoData aData(mAlloc); // for malloc/copy of outgoing data
659
660 /* query for each OID we know about */
661 for(currOidDex=0; currOidDex<NUM_KNOWN_FIELDS; currOidDex++) {
662 const oidToFieldFuncs *fieldFuncs = &crlFieldTable[currOidDex];
663 currOid = fieldFuncs->fieldId;
664 uint32 numFields; // for THIS oid
665
666 /*
667 * Return false if field not there, which is not an error here.
668 * Actual exceptions are fatal.
669 */
670 if(!fieldFuncs->getFcn(*this,
671 0, // index - looking for first one
672 numFields,
673 aData)) {
674 continue;
675 }
676
677 /* got some data for this oid - copy it and oid to outgoing CrlFields */
678 assert(numOutFields < maxFields);
679 currOutField = &outFields[numOutFields];
680 currOutField->FieldValue = aData.release();
681 aData.copy(*currOid);
682 currOutField->FieldOid = aData.release();
683 numOutFields++;
684
685 /* if more fields are available for this OID, snag them too */
686 for(uint32 fieldDex=1; fieldDex<numFields; fieldDex++) {
687 /* note this should always succeed */
688 bool brtn = fieldFuncs->getFcn(*this,
689 fieldDex,
690 numFields, // shouldn't change
691 aData);
692 if(!brtn) {
693 clErrorLog("getAllParsedCrlFields: index screwup");
694 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
695 }
696 assert(numOutFields < maxFields);
697 currOutField = &outFields[numOutFields];
698 currOutField->FieldValue = aData.release();
699 aData.copy(*currOid);
700 currOutField->FieldOid = aData.release();
701 numOutFields++;
702 } /* multiple fields for currOid */
703 } /* for each known OID */
704
705 NumberOfFields = numOutFields;
706 CrlFields = outFields;
707 }
708
709 void
710 DecodedCrl::describeFormat(
711 CssmAllocator &alloc,
712 uint32 &NumberOfFields,
713 CSSM_OID_PTR &OidList)
714 {
715 /* malloc in app's space, do deep copy (including ->Data) */
716 CSSM_OID_PTR oidList = (CSSM_OID_PTR)alloc.malloc(
717 NUM_KNOWN_FIELDS * sizeof(CSSM_OID));
718 memset(oidList, 0, NUM_KNOWN_FIELDS * sizeof(CSSM_OID));
719 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) {
720 CssmAutoData oidCopy(alloc, *crlFieldTable[i].fieldId);
721 oidList[i] = oidCopy.release();
722 }
723 NumberOfFields = NUM_KNOWN_FIELDS;
724 OidList = oidList;
725 }