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 40static 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 ***/ 48static 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 65static 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 ***/ 79static 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 105static 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 ***/ 121static 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 132static 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 143static 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 154static 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 ***/ 169static 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 ***/ 187static 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 */ 207static 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 237static 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 257static 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 282static 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 ***/ 304static 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 356static 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 364static 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 */ 412typedef 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 421static 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 */ 486static 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 */ 504static 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 */ 530static 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 */ 583bool 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 */ 607void 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 */ 635void 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 */ 647void 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 716void 717DecodedCrl::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} 733