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_utilities/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/utilities.h> 36#include <Security/oidscrl.h> 37#include <Security/oidscert.h> 38#include <Security/cssmerr.h> 39#include <Security/x509defs.h> 40 41static void CL_freeCssmExtensions( 42 CSSM_X509_EXTENSIONS &extens, 43 Allocator &alloc); 44 45/*** 46 *** Version 47 *** Format = DER-encoded int (max of four bytes in this case) 48 ***/ 49static 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 66static 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 ***/ 80static 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 106static 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 ***/ 122static 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 133static 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 144static 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 155static 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 ***/ 170static 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 ***/ 188static 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 */ 208static void nssRevokedEntryToCssm( 209 NSS_RevokedCert &nssEntry, 210 CSSM_X509_REVOKED_CERT_ENTRY &cssmEntry, 211 Allocator &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 238static void freeCssmEntry( 239 CSSM_X509_REVOKED_CERT_ENTRY_PTR cssmEntry, 240 Allocator &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 258static void nssRevokedListToCssm( 259 NSS_RevokedCert **nssList, // may be NULL 260 CSSM_X509_REVOKED_CERT_LIST_PTR cssmList, 261 Allocator &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 283static void freeCssmRevokedList( 284 CSSM_X509_REVOKED_CERT_LIST_PTR cssmList, 285 Allocator &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 ***/ 305static bool getField_SignedCrl ( 306 DecodedItem &item, 307 unsigned index, // which occurrence (0 = first) 308 uint32 &numFields, // RETURNED 309 CssmOwnedData &fieldValue) // RETURNED 310{ 311 Allocator &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 357static 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 365static 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 Allocator &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 */ 413typedef 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 422static 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 477 { &CSSMOID_CrlDistributionPoints, // get/set not implemented 478 &getField_Unimplemented, &setField_ReadOnly, 479 &freeFieldCrlDistributionPoints}, 480 // etc.. 481}; 482 483#define NUM_KNOWN_FIELDS (sizeof(crlFieldTable) / sizeof(oidToFieldFuncs)) 484#define NUM_STD_CRL_FIELDS 2 /* TBD not including extensions */ 485 486/* map an OID to an oidToFieldFuncs */ 487static const oidToFieldFuncs *oidToFields( 488 const CssmOid &fieldId) 489{ 490 const oidToFieldFuncs *fieldTable = crlFieldTable; 491 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) { 492 if(fieldId == CssmData::overlay(*fieldTable->fieldId)) { 493 return fieldTable; 494 } 495 fieldTable++; 496 } 497 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); 498} 499 500/* 501 * Common routine to free OID-specific field data. Used in the 502 * public DecodedCrl::freeCrlFieldData and when freeing 503 * extensions in a CSSM_X509_TBS_CERTLIST. 504 */ 505static void CL_freeCrlFieldData( 506 const CssmOid &fieldId, 507 CssmOwnedData &fieldValue, 508 bool reset = true) 509{ 510 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) { 511 CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER); 512 } 513 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); 514 if(fieldFuncs->freeFcn != NULL) { 515 /* optional - simple cases handled below */ 516 fieldFuncs->freeFcn(fieldValue); 517 } 518 if(reset) { 519 fieldValue.reset(); 520 fieldValue.release(); 521 } 522} 523 524/* 525 * Common routime to free a CSSM_X509_EXTENSIONS. Used to free 526 * CSSM_X509_TBS_CERTLIST.extensions and 527 * CSSM_X509_REVOKED_CERT_ENTRY.extensions. 528 * We just cook up a CssmOid and a CssmOwnedData for each extension 529 * and pass to CL_freeCrlFieldData(). 530 */ 531static void CL_freeCssmExtensions( 532 CSSM_X509_EXTENSIONS &extens, 533 Allocator &alloc) 534{ 535 for(uint32 dex=0; dex<extens.numberOfExtensions; dex++) { 536 CSSM_X509_EXTENSION_PTR exten = &extens.extensions[dex]; 537 const CSSM_OID *fieldOid; 538 539 /* 540 * The field OID is either the same as the extension's OID (if we parsed 541 * it) or CSSMOID_X509V3CertificateExtensionCStruct (if we didn't). 542 */ 543 switch(exten->format) { 544 case CSSM_X509_DATAFORMAT_ENCODED: 545 fieldOid = &CSSMOID_X509V3CertificateExtensionCStruct; 546 break; 547 case CSSM_X509_DATAFORMAT_PARSED: 548 case CSSM_X509_DATAFORMAT_PAIR: 549 fieldOid = &exten->extnId; 550 break; 551 default: 552 clErrorLog("CL_freeCssmExtensions: bad exten->format (%d)", 553 (int)exten->format); 554 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 555 } 556 557 const CssmOid &fieldId = CssmOid::overlay(*fieldOid); 558 559 if (exten->extnId.Data != NULL) // if this is null, something threw when it was instantiated 560 { 561 CssmData cData((uint8 *)exten, sizeof(CSSM_X509_EXTENSION)); 562 CssmRemoteData fieldValue(alloc, cData); 563 CL_freeCrlFieldData(fieldId, fieldValue, false); 564 fieldValue.release(); // but no free (via reset() */ 565 } 566 } 567 alloc.free(extens.extensions); 568 memset(&extens, 0, sizeof(CSSM_X509_EXTENSIONS)); 569} 570 571 572 573/*** 574 *** Public functions 575 ***/ 576 577/* 578 * Obtain the index'th occurrence of field specified by fieldId in specified cert. 579 * Format of the returned field depends on fieldId. 580 * Returns total number of fieldId fields in the cert if index is 0. 581 * FieldValue assumed to be empty on entry. 582 * Returns true if specified field was found, else returns false. 583 */ 584bool DecodedCrl::getCrlFieldData( 585 const CssmOid &fieldId, // which field 586 unsigned index, // which occurrence (0 = first) 587 uint32 &numFields, // RETURNED 588 CssmOwnedData &fieldValue) // RETURNED 589{ 590 switch(mState) { 591 case IS_Empty: 592 case IS_Building: 593 clErrorLog("DecodedCrl::getCrlField: can't parse undecoded CRL!"); 594 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 595 case IS_DecodedAll: 596 case IS_DecodedTBS: 597 break; 598 } 599 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); 600 return fieldFuncs->getFcn(*this, index, numFields, fieldValue); 601} 602 603/* 604 * Set the field specified by fieldId in the specified Cert. 605 * Note no index - individual field routines either append (for extensions) 606 * or if field already set ::throwMe(for all others) 607 */ 608void DecodedCrl::setCrlField( 609 const CssmOid &fieldId, // which field 610 const CssmData &fieldValue) 611{ 612 switch(mState) { 613 case IS_Empty: // first time thru 614 mState = IS_Building; 615 break; 616 case IS_Building: // subsequent passes 617 break; 618 case IS_DecodedAll: 619 case IS_DecodedTBS: 620 clErrorLog("DecodedCrl::setCrlField: can't build on a decoded CRL!"); 621 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 622 } 623 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) { 624 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 625 } 626 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); 627 const CssmData &value = CssmData::overlay(fieldValue); 628 fieldFuncs->setFcn(*this, value); 629} 630 631/* 632 * Free the fieldId-specific data referred to by fieldValue->Data. 633 * No state from DecodedCrl needed; use the routine shared with 634 * CL_freeCssmExtensions(). 635 */ 636void DecodedCrl::freeCrlFieldData( 637 const CssmOid &fieldId, 638 CssmOwnedData &fieldValue) 639{ 640 CL_freeCrlFieldData(fieldId, fieldValue); 641} 642 643 644/* 645 * Common means to get all fields from a decoded CRL. Used in 646 * CrlGetAllTemplateFields and CrlGetAllFields. 647 */ 648void DecodedCrl::getAllParsedCrlFields( 649 uint32 &NumberOfFields, // RETURNED 650 CSSM_FIELD_PTR &CrlFields) // RETURNED 651{ 652 /* this is the max - some might be missing */ 653 uint32 maxFields = NUM_STD_CRL_FIELDS + mDecodedExtensions.numExtensions(); 654 CSSM_FIELD_PTR outFields = (CSSM_FIELD_PTR)mAlloc.malloc( 655 maxFields * sizeof(CSSM_FIELD)); 656 657 /* 658 * We'll be copying oids and values for fields we find into 659 * outFields; current number of valid fields found in numOutFields. 660 */ 661 memset(outFields, 0, maxFields * sizeof(CSSM_FIELD)); 662 uint32 numOutFields = 0; 663 CSSM_FIELD_PTR currOutField; 664 uint32 currOidDex; 665 const CSSM_OID *currOid; 666 CssmAutoData aData(mAlloc); // for malloc/copy of outgoing data 667 668 /* query for each OID we know about */ 669 for(currOidDex=0; currOidDex<NUM_KNOWN_FIELDS; currOidDex++) { 670 const oidToFieldFuncs *fieldFuncs = &crlFieldTable[currOidDex]; 671 currOid = fieldFuncs->fieldId; 672 uint32 numFields; // for THIS oid 673 674 /* 675 * Return false if field not there, which is not an error here. 676 * Actual exceptions are fatal. 677 */ 678 if(!fieldFuncs->getFcn(*this, 679 0, // index - looking for first one 680 numFields, 681 aData)) { 682 continue; 683 } 684 685 /* got some data for this oid - copy it and oid to outgoing CrlFields */ 686 assert(numOutFields < maxFields); 687 currOutField = &outFields[numOutFields]; 688 currOutField->FieldValue = aData.release(); 689 aData.copy(*currOid); 690 currOutField->FieldOid = aData.release(); 691 numOutFields++; 692 693 /* if more fields are available for this OID, snag them too */ 694 for(uint32 fieldDex=1; fieldDex<numFields; fieldDex++) { 695 /* note this should always succeed */ 696 bool brtn = fieldFuncs->getFcn(*this, 697 fieldDex, 698 numFields, // shouldn't change 699 aData); 700 if(!brtn) { 701 clErrorLog("getAllParsedCrlFields: index screwup"); 702 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 703 } 704 assert(numOutFields < maxFields); 705 currOutField = &outFields[numOutFields]; 706 currOutField->FieldValue = aData.release(); 707 aData.copy(*currOid); 708 currOutField->FieldOid = aData.release(); 709 numOutFields++; 710 } /* multiple fields for currOid */ 711 } /* for each known OID */ 712 713 NumberOfFields = numOutFields; 714 CrlFields = outFields; 715} 716 717void 718DecodedCrl::describeFormat( 719 Allocator &alloc, 720 uint32 &NumberOfFields, 721 CSSM_OID_PTR &OidList) 722{ 723 /* malloc in app's space, do deep copy (including ->Data) */ 724 CSSM_OID_PTR oidList = (CSSM_OID_PTR)alloc.malloc( 725 NUM_KNOWN_FIELDS * sizeof(CSSM_OID)); 726 memset(oidList, 0, NUM_KNOWN_FIELDS * sizeof(CSSM_OID)); 727 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) { 728 CssmAutoData oidCopy(alloc, *crlFieldTable[i].fieldId); 729 oidList[i] = oidCopy.release(); 730 } 731 NumberOfFields = NUM_KNOWN_FIELDS; 732 OidList = oidList; 733} 734