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