1/* 2 * Copyright (c) 2003 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 * clNameUtils.cpp - support for Name, GeneralizedName, all sorts of names 20 */ 21 22#include "clNameUtils.h" 23#include "clNssUtils.h" 24#include "cldebugging.h" 25#include <security_utilities/utilities.h> 26 27#pragma mark ----- NSS_Name <--> CSSM_X509_NAME ----- 28 29/* 30 * NSS_ATV --> CSSM_X509_TYPE_VALUE_PAIR 31 */ 32static 33void CL_nssAtvToCssm( 34 const NSS_ATV &nssObj, 35 CSSM_X509_TYPE_VALUE_PAIR &cssmObj, 36 Allocator &alloc) 37{ 38 /* tag and decoded data */ 39 cssmObj.valueType = nssObj.value.tag; 40 clAllocCopyData(alloc, nssObj.value.item, cssmObj.value); 41 /* the OID */ 42 clAllocCopyData(alloc, nssObj.type, cssmObj.type); 43} 44 45/* NSS_RDN --> CSSM_X509_RDN */ 46void CL_nssRdnToCssm( 47 const NSS_RDN &nssObj, 48 CSSM_X509_RDN &cssmObj, 49 Allocator &alloc, 50 SecNssCoder &coder) // conversion requires further decoding 51{ 52 memset(&cssmObj, 0, sizeof(cssmObj)); 53 unsigned numAtvs = clNssArraySize((const void **)nssObj.atvs); 54 if(numAtvs == 0) { 55 return; 56 } 57 58 size_t len = numAtvs * sizeof(CSSM_X509_TYPE_VALUE_PAIR); 59 cssmObj.AttributeTypeAndValue = 60 (CSSM_X509_TYPE_VALUE_PAIR_PTR)alloc.malloc(len); 61 cssmObj.numberOfPairs = numAtvs; 62 CSSM_X509_TYPE_VALUE_PAIR_PTR cssmAtvs = cssmObj.AttributeTypeAndValue; 63 memset(cssmAtvs, 0, len); 64 65 for(unsigned dex=0; dex<numAtvs; dex++) { 66 CL_nssAtvToCssm(*(nssObj.atvs[dex]), cssmAtvs[dex], alloc); 67 } 68 return; 69} 70 71/* NSS_Name --> CSSM_X509_NAME */ 72void CL_nssNameToCssm( 73 const NSS_Name &nssObj, 74 CSSM_X509_NAME &cssmObj, 75 Allocator &alloc) 76{ 77 memset(&cssmObj, 0, sizeof(cssmObj)); 78 unsigned numRdns = clNssArraySize((const void **)nssObj.rdns); 79 if(numRdns == 0) { 80 /* not technically an error */ 81 return; 82 } 83 84 size_t len = numRdns * sizeof(CSSM_X509_RDN); 85 cssmObj.RelativeDistinguishedName = (CSSM_X509_RDN_PTR)alloc.malloc(len); 86 cssmObj.numberOfRDNs = numRdns; 87 CSSM_X509_RDN_PTR cssmRdns = cssmObj.RelativeDistinguishedName; 88 memset(cssmRdns, 0, len); 89 90 SecNssCoder coder; // conversion requires further decoding 91 92 for(unsigned dex=0; dex<numRdns; dex++) { 93 CL_nssRdnToCssm(*(nssObj.rdns[dex]), cssmRdns[dex], alloc, coder); 94 } 95 return; 96} 97 98/* 99 * CSSM_X509_TYPE_VALUE_PAIR --> NSS_ATV 100 */ 101void CL_cssmAtvToNss( 102 const CSSM_X509_TYPE_VALUE_PAIR &cssmObj, 103 NSS_ATV &nssObj, 104 SecNssCoder &coder) 105{ 106 memset(&nssObj, 0, sizeof(nssObj)); 107 108 /* copy the OID */ 109 coder.allocCopyItem(cssmObj.type, nssObj.type); 110 111 /* tag and value */ 112 nssObj.value.tag = cssmObj.valueType; 113 coder.allocCopyItem(cssmObj.value, nssObj.value.item); 114} 115 116/* CSSM_X509_RDN --> NSS_RDN */ 117void CL_cssmRdnToNss( 118 const CSSM_X509_RDN &cssmObj, 119 NSS_RDN &nssObj, 120 SecNssCoder &coder) 121{ 122 memset(&nssObj, 0, sizeof(nssObj)); 123 124 /* alloc NULL-terminated array of ATV pointers */ 125 unsigned numAtvs = cssmObj.numberOfPairs; 126 unsigned size = (numAtvs + 1) * sizeof(void *); 127 nssObj.atvs = (NSS_ATV **)coder.malloc(size); 128 memset(nssObj.atvs, 0, size); 129 130 /* grind thru the elements */ 131 for(unsigned atvDex=0; atvDex<numAtvs; atvDex++) { 132 nssObj.atvs[atvDex] = (NSS_ATV *)coder.malloc(sizeof(NSS_ATV)); 133 CL_cssmAtvToNss(cssmObj.AttributeTypeAndValue[atvDex], 134 *nssObj.atvs[atvDex], coder); 135 } 136} 137 138/* CSSM_X509_NAME --> NSS_Name */ 139void CL_cssmNameToNss( 140 const CSSM_X509_NAME &cssmObj, 141 NSS_Name &nssObj, 142 SecNssCoder &coder) 143{ 144 memset(&nssObj, 0, sizeof(nssObj)); 145 146 /* alloc NULL-terminated array of RDN pointers */ 147 unsigned numRdns = cssmObj.numberOfRDNs; 148 nssObj.rdns = (NSS_RDN **)clNssNullArray(numRdns, coder); 149 150 /* grind thru the elements */ 151 for(unsigned rdnDex=0; rdnDex<numRdns; rdnDex++) { 152 nssObj.rdns[rdnDex] = (NSS_RDN *)coder.malloc(sizeof(NSS_RDN)); 153 CL_cssmRdnToNss(cssmObj.RelativeDistinguishedName[rdnDex], 154 *nssObj.rdns[rdnDex], coder); 155 } 156} 157 158#pragma mark ----- Name Normalization ----- 159 160void CL_normalizeString( 161 char *strPtr, 162 int &strLen) // IN/OUT 163{ 164 char *pCh = strPtr; // working ptr 165 char *pD = pCh; // start of good string chars 166 char *pEos = pCh + strLen - 1; 167 168 if(strLen == 0) { 169 return; 170 } 171 172 /* adjust if Length included NULL terminator */ 173 while(*pEos == 0) { 174 pEos--; 175 } 176 177 /* Remove trailing spaces */ 178 while(isspace(*pEos)) { 179 pEos--; 180 } 181 182 /* Point to one past last non-space character */ 183 pEos++; 184 185 /* upper case */ 186 while(pCh < pEos) { 187 *pCh = toupper(*pCh); 188 pCh++; 189 } 190 191 /* clean out whitespace */ 192 /* 193 * 1. skip all leading whitespace 194 */ 195 pCh = pD; 196 while(isspace(*pCh) && (pCh < pEos)) { 197 pCh++; 198 } 199 200 /* 201 * 2. eliminate multiple whitespace. 202 * pCh points to first non-white char. 203 * pD still points to start of string 204 */ 205 char ch; 206 while(pCh < pEos) { 207 ch = *pCh++; 208 *pD++ = ch; // normal case 209 if( isspace(ch) ){ 210 /* skip 'til next nonwhite */ 211 while(isspace(*pCh) && (pCh < pEos)) { 212 pCh++; 213 } 214 } 215 }; 216 217 strLen = (int)(pD - strPtr); 218} 219 220/* 221 * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case 222 * insensitive and we're supposed to ignore leading and trailing 223 * whitespace, and collapse multiple whitespace characters into one. 224 * 225 * Incoming NSS_Name is assumed to be entirely within specifed coder's 226 * address space; we'll be munging some of that and possibly replacing 227 * some pointers with others allocated from the same space. 228 */ 229void CL_normalizeX509NameNSS( 230 NSS_Name &nssName, 231 SecNssCoder &coder) 232{ 233 unsigned numRdns = clNssArraySize((const void **)nssName.rdns); 234 if(numRdns == 0) { 235 /* not technically an error */ 236 return; 237 } 238 239 for(unsigned rdnDex=0; rdnDex<numRdns; rdnDex++) { 240 NSS_RDN *rdn = nssName.rdns[rdnDex]; 241 assert(rdn != NULL); 242 unsigned numAttrs = clNssArraySize((const void **)rdn->atvs); 243 if(numAttrs == 0) { 244 clFieldLog("clNormalizeX509Name: zero numAttrs at index %d", rdnDex); 245 continue; 246 } 247 248 /* descend into array of attribute/values */ 249 for(unsigned attrDex=0; attrDex<numAttrs; attrDex++) { 250 NSS_ATV *attr = rdn->atvs[attrDex]; 251 assert(attr != NULL); 252 253 /* 254 * attr->value is an ASN_ANY containing an encoded 255 * string. We only normalize Prinatable String types. 256 * If we find one, decode it, normalize it, encode the 257 * result, and put the encoding back in attr->value. 258 * We temporarily "leak" the original string, which only 259 * has a lifetime of the incoming SecNssCoder. 260 */ 261 NSS_TaggedItem &attrVal = attr->value; 262 if(attrVal.tag != SEC_ASN1_PRINTABLE_STRING) { 263 /* skip it */ 264 continue; 265 } 266 267 /* normalize */ 268 char *strPtr = (char *)attrVal.item.Data; 269 int newLen = (int)attrVal.item.Length; 270 CL_normalizeString(strPtr, newLen); 271 272 /* possible length adjustment */ 273 attrVal.item.Length = newLen; 274 } /* for each attribute/value */ 275 } /* for each RDN */ 276} 277 278#pragma mark ----- CE_GeneralNames <--> NSS_GeneralNames ----- 279 280void CL_nssGeneralNameToCssm( 281 NSS_GeneralName &nssObj, 282 CE_GeneralName &cdsaObj, 283 SecNssCoder &coder, // for temp decoding 284 Allocator &alloc) // destination 285{ 286 memset(&cdsaObj, 0, sizeof(cdsaObj)); 287 PRErrorCode prtn; 288 289 /* for caller's CE_GeneralName */ 290 CSSM_BOOL berEncoded = CSSM_FALSE; 291 CE_GeneralNameType cdsaTag; 292 293 /* 294 * At this point, depending on the decoded object's tag, we either 295 * have the final bytes to copy out, or we need to decode further. 296 * After this switch, if doCopy is true, give the caller a copy 297 * of nssObj.item. 298 */ 299 bool doCopy = true; 300 switch(nssObj.tag) { 301 case NGT_OtherName: // ASN_ANY -> CE_OtherName 302 { 303 cdsaTag = GNT_OtherName; 304 305 /* decode to coder memory */ 306 CE_OtherName *nssOther = 307 (CE_OtherName *)coder.malloc(sizeof(CE_OtherName)); 308 memset(nssOther, 0, sizeof(CE_OtherName)); 309 prtn = coder.decodeItem(nssObj.item, 310 kSecAsn1GenNameOtherNameTemplate, 311 nssOther); 312 if(prtn) { 313 clErrorLog("CL_nssGeneralNameToCssm: error decoding " 314 "OtherName\n"); 315 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 316 } 317 318 /* copy out to caller */ 319 clAllocData(alloc, cdsaObj.name, sizeof(CE_OtherName)); 320 clCopyOtherName(*nssOther, *((CE_OtherName *)cdsaObj.name.Data), 321 alloc); 322 doCopy = false; 323 break; 324 } 325 case NGT_RFC822Name: // IA5String, done 326 cdsaTag = GNT_RFC822Name; 327 break; 328 case NGT_DNSName: // IA5String 329 cdsaTag = GNT_DNSName; 330 break; 331 case NGT_X400Address: // ASY_ANY, leave alone 332 cdsaTag = GNT_X400Address; 333 berEncoded = CSSM_TRUE; 334 break; 335 case NGT_DirectoryName: // ASN_ANY --> NSS_Name 336 { 337 cdsaTag = GNT_DirectoryName; 338 339 /* Decode to coder memory */ 340 NSS_Name *nssName = (NSS_Name *)coder.malloc(sizeof(NSS_Name)); 341 memset(nssName, 0, sizeof(NSS_Name)); 342 prtn = coder.decodeItem(nssObj.item, kSecAsn1NameTemplate, nssName); 343 if(prtn) { 344 clErrorLog("CL_nssGeneralNameToCssm: error decoding " 345 "NSS_Name\n"); 346 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 347 } 348 349 /* convert & copy out to caller */ 350 clAllocData(alloc, cdsaObj.name, sizeof(CSSM_X509_NAME)); 351 CL_nssNameToCssm(*nssName, 352 *((CSSM_X509_NAME *)cdsaObj.name.Data), alloc); 353 doCopy = false; 354 break; 355 } 356 case NGT_EdiPartyName: // ASN_ANY, leave alone 357 cdsaTag = GNT_EdiPartyName; 358 berEncoded = CSSM_TRUE; 359 break; 360 case NGT_URI: // IA5String 361 cdsaTag = GNT_URI; 362 break; 363 case NGT_IPAddress: // OCTET_STRING 364 cdsaTag = GNT_IPAddress; 365 break; 366 case NGT_RegisteredID: // OID 367 cdsaTag = GNT_RegisteredID; 368 break; 369 default: 370 clErrorLog("CL_nssGeneralNameToCssm: bad name tag\n"); 371 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 372 } 373 374 cdsaObj.nameType = cdsaTag; 375 cdsaObj.berEncoded = berEncoded; 376 if(doCopy) { 377 clAllocCopyData(alloc, nssObj.item, cdsaObj.name); 378 } 379} 380 381void CL_nssGeneralNamesToCssm( 382 const NSS_GeneralNames &nssObj, 383 CE_GeneralNames &cdsaObj, 384 SecNssCoder &coder, // for temp decoding 385 Allocator &alloc) // destination 386{ 387 memset(&cdsaObj, 0, sizeof(cdsaObj)); 388 unsigned numNames = clNssArraySize((const void **)nssObj.names); 389 if(numNames == 0) { 390 return; 391 } 392 393 /* 394 * Decode each name element, currently a raw ASN_ANY blob. 395 * Then convert each result into CDSA form. 396 * This array of (NSS_GeneralName)s is temporary, it doesn't 397 * persist outside of this routine other than the fact that it's 398 * mallocd by the coder arena pool. 399 */ 400 NSS_GeneralName *names = 401 (NSS_GeneralName *)coder.malloc(sizeof(NSS_GeneralName) * numNames); 402 memset(names, 0, sizeof(NSS_GeneralName) * numNames); 403 cdsaObj.generalName = (CE_GeneralName *)alloc.malloc( 404 sizeof(CE_GeneralName) * numNames); 405 cdsaObj.numNames = numNames; 406 407 for(unsigned dex=0; dex<numNames; dex++) { 408 if(coder.decodeItem(*nssObj.names[dex], kSecAsn1GeneralNameTemplate, 409 &names[dex])) { 410 clErrorLog("***CL_nssGeneralNamesToCssm: Error decoding " 411 "General.name\n"); 412 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 413 } 414 415 CL_nssGeneralNameToCssm(names[dex], 416 cdsaObj.generalName[dex], 417 coder, alloc); 418 } 419} 420 421void CL_cssmGeneralNameToNss( 422 CE_GeneralName &cdsaObj, 423 NSS_GeneralName &nssObj, // actually an NSSTaggedItem 424 SecNssCoder &coder) // for temp decoding 425{ 426 memset(&nssObj, 0, sizeof(nssObj)); 427 428 /* 429 * The default here is just to use the app-supplied data as is... 430 */ 431 nssObj.item = cdsaObj.name; 432 unsigned char itemTag; // for nssObj.tag 433 bool doCopy = false; // unless we have to modify tag byte 434 unsigned char overrideTag; // to force context-specific tag for 435 // an ASN_ANY 436 PRErrorCode prtn; 437 438 switch(cdsaObj.nameType) { 439 case GNT_OtherName: 440 /* 441 * Caller supplies an CE_OtherName. Encode it. 442 */ 443 if((cdsaObj.name.Length != sizeof(CE_OtherName)) || 444 (cdsaObj.name.Data == NULL)) { 445 clErrorLog("CL_cssmGeneralNameToNss: OtherName.Length" 446 " error\n"); 447 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 448 } 449 prtn = coder.encodeItem(cdsaObj.name.Data, 450 kSecAsn1OtherNameTemplate, nssObj.item); 451 if(prtn) { 452 clErrorLog("CL_cssmGeneralNameToNss: OtherName encode" 453 " error\n"); 454 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 455 } 456 itemTag = NGT_OtherName; 457 break; 458 case GNT_RFC822Name: // IA5String 459 itemTag = NGT_RFC822Name; 460 break; 461 case GNT_DNSName: // IA5String 462 itemTag = NGT_DNSName; 463 break; 464 case GNT_X400Address: // caller's resposibility 465 /* 466 * Encoded as ASN_ANY, the only thing we do is to 467 * force the correct context-specific tag 468 */ 469 itemTag = GNT_X400Address; 470 if(!cdsaObj.berEncoded) { 471 clErrorLog("CL_cssmGeneralNameToNss: X400Address must" 472 " be BER-encoded\n"); 473 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 474 } 475 overrideTag = SEC_ASN1_CONTEXT_SPECIFIC | 476 SEC_ASN1_CONSTRUCTED | NGT_X400Address; 477 doCopy = true; 478 break; 479 case GNT_DirectoryName: 480 { 481 /* 482 * Caller supplies an CSSM_X509_NAME. Convert to NSS 483 * format and encode it. 484 */ 485 if((cdsaObj.name.Length != sizeof(CSSM_X509_NAME)) || 486 (cdsaObj.name.Data == NULL)) { 487 clErrorLog("CL_cssmGeneralNameToNss: DirectoryName.Length" 488 " error\n"); 489 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 490 } 491 NSS_Name nssName; 492 CSSM_X509_NAME_PTR cdsaName = 493 (CSSM_X509_NAME_PTR)cdsaObj.name.Data; 494 CL_cssmNameToNss(*cdsaName, nssName, coder); 495 prtn = coder.encodeItem(&nssName, 496 kSecAsn1NameTemplate, nssObj.item); 497 if(prtn) { 498 clErrorLog("CL_cssmGeneralNameToNss: X509Name encode" 499 " error\n"); 500 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 501 } 502 itemTag = GNT_DirectoryName; 503 504 /* 505 * AND, munge the tag to make it a context-specific 506 * sequence 507 * no, not needed, this is wrapped in an explicit... 508 */ 509 //nssObj.item.Data[0] = SEC_ASN1_CONTEXT_SPECIFIC | 510 // SEC_ASN1_CONSTRUCTED | GNT_DirectoryName; 511 512 break; 513 } 514 case GNT_EdiPartyName: // caller's resposibility 515 /* 516 * Encoded as ASN_ANY, the only thing we do is to 517 * force the correct context-specific tag 518 */ 519 itemTag = GNT_EdiPartyName; 520 if(!cdsaObj.berEncoded) { 521 clErrorLog("CL_cssmGeneralNameToNss: EdiPartyName must" 522 " be BER-encoded\n"); 523 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 524 } 525 overrideTag = SEC_ASN1_CONTEXT_SPECIFIC | NGT_X400Address; 526 doCopy = true; 527 break; 528 case GNT_URI: // IA5String 529 itemTag = GNT_URI; 530 break; 531 case GNT_IPAddress: // OCTET_STRING 532 itemTag = NGT_IPAddress; 533 break; 534 case GNT_RegisteredID: // OID 535 itemTag = NGT_RegisteredID; 536 break; 537 default: 538 clErrorLog("CL_cssmGeneralNameToNss: bad name tag\n"); 539 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); 540 } 541 if(doCopy) { 542 coder.allocCopyItem(cdsaObj.name, nssObj.item); 543 nssObj.item.Data[0] = overrideTag; 544 } 545 nssObj.tag = itemTag; 546} 547 548void CL_cssmGeneralNamesToNss( 549 const CE_GeneralNames &cdsaObj, 550 NSS_GeneralNames &nssObj, 551 SecNssCoder &coder) 552{ 553 uint32 numNames = cdsaObj.numNames; 554 nssObj.names = (CSSM_DATA **)clNssNullArray(numNames, coder); 555 556 /* 557 * Convert each element in cdsaObj to NSS form, encode, drop into 558 * the ASN_ANY array. 559 * 560 * This array of (NSS_GeneralName)s is temporary, it doesn't 561 * persist outside of this routine other than the fact that it's 562 * mallocd by the coder arena pool. 563 */ 564 NSS_GeneralName *names = 565 (NSS_GeneralName *)coder.malloc(sizeof(NSS_GeneralName) * numNames); 566 memset(names, 0, sizeof(NSS_GeneralName) * numNames); 567 for(unsigned dex=0; dex<cdsaObj.numNames; dex++) { 568 nssObj.names[dex] = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA)); 569 memset(nssObj.names[dex], 0, sizeof(CSSM_DATA)); 570 CL_cssmGeneralNameToNss(cdsaObj.generalName[dex], 571 names[dex], coder); 572 if(coder.encodeItem(&names[dex], kSecAsn1GeneralNameTemplate, 573 *nssObj.names[dex])) { 574 clErrorLog("***Error encoding General.name\n"); 575 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 576 } 577 } 578} 579 580/* Copy a CE_OtherName */ 581void clCopyOtherName( 582 const CE_OtherName &src, 583 CE_OtherName &dst, 584 Allocator &alloc) 585{ 586 clAllocCopyData(alloc, src.typeId, dst.typeId); 587 clAllocCopyData(alloc, src.value, dst.value); 588} 589 590#pragma mark ----- Name-related Free ----- 591 592void CL_freeAuthorityKeyId( 593 CE_AuthorityKeyID &cdsaObj, 594 Allocator &alloc) 595{ 596 alloc.free(cdsaObj.keyIdentifier.Data); 597 CL_freeCssmGeneralNames(cdsaObj.generalNames, alloc); 598 alloc.free(cdsaObj.generalNames); 599 alloc.free(cdsaObj.serialNumber.Data); 600 memset(&cdsaObj, 0, sizeof(CE_AuthorityKeyID)); 601} 602 603void CL_freeCssmGeneralName( 604 CE_GeneralName &genName, 605 Allocator &alloc) 606{ 607 switch(genName.nameType) { 608 /* 609 * Two special cases here. 610 */ 611 case GNT_DirectoryName: 612 if((!genName.berEncoded) && // we're flexible 613 (genName.name.Length == 614 sizeof(CSSM_X509_NAME))) { // paranoia 615 CL_freeX509Name((CSSM_X509_NAME_PTR)genName.name.Data, alloc); 616 } 617 break; 618 619 case GNT_OtherName: 620 if((!genName.berEncoded) && // we're flexible 621 (genName.name.Length == 622 sizeof(CE_OtherName))) { // paranoia 623 CE_OtherName *con = (CE_OtherName *)genName.name.Data; 624 CL_freeOtherName(con, alloc); 625 } 626 break; 627 default: 628 break; 629 } 630 /* and always free this */ 631 alloc.free(genName.name.Data); 632} 633 634void CL_freeCssmGeneralNames( 635 CE_GeneralNames *cdsaObj, 636 Allocator &alloc) 637{ 638 if(cdsaObj == NULL) { 639 return; 640 } 641 for(unsigned i=0; i<cdsaObj->numNames; i++) { 642 CL_freeCssmGeneralName(cdsaObj->generalName[i], alloc); 643 } 644 if(cdsaObj->numNames) { 645 memset(cdsaObj->generalName, 0, cdsaObj->numNames * sizeof(CE_GeneralName)); 646 alloc.free(cdsaObj->generalName); 647 } 648 memset(cdsaObj, 0, sizeof(CE_GeneralNames)); 649} 650 651void CL_freeCssmDistPointName( 652 CE_DistributionPointName *cssmDpn, 653 Allocator &alloc) 654{ 655 if(cssmDpn == NULL) { 656 return; 657 } 658 switch(cssmDpn->nameType) { 659 case CE_CDNT_FullName: 660 CL_freeCssmGeneralNames(cssmDpn->dpn.fullName, alloc); 661 alloc.free(cssmDpn->dpn.fullName); 662 break; 663 case CE_CDNT_NameRelativeToCrlIssuer: 664 CL_freeX509Rdn(cssmDpn->dpn.rdn, alloc); 665 alloc.free(cssmDpn->dpn.rdn); 666 break; 667 } 668 memset(cssmDpn, 0, sizeof(*cssmDpn)); 669} 670 671void CL_freeCssmDistPoints( 672 CE_CRLDistPointsSyntax *cssmDps, 673 Allocator &alloc) 674{ 675 if(cssmDps == NULL) { 676 return; 677 } 678 for(unsigned dex=0; dex<cssmDps->numDistPoints; dex++) { 679 CE_CRLDistributionPoint *cssmDp = &cssmDps->distPoints[dex]; 680 if(cssmDp->distPointName) { 681 CL_freeCssmDistPointName(cssmDp->distPointName, alloc); 682 alloc.free(cssmDp->distPointName); 683 } 684 if(cssmDp->crlIssuer) { 685 CL_freeCssmGeneralNames(cssmDp->crlIssuer, alloc); 686 alloc.free(cssmDp->crlIssuer); 687 } 688 } 689 memset(cssmDps->distPoints, 0, 690 cssmDps->numDistPoints * sizeof(CE_CRLDistributionPoint)); 691 alloc.free(cssmDps->distPoints); 692 memset(cssmDps, 0, sizeof(*cssmDps)); 693} 694 695/* free contents of an CSSM_X509_NAME */ 696void CL_freeX509Name( 697 CSSM_X509_NAME_PTR x509Name, 698 Allocator &alloc) 699{ 700 if(x509Name == NULL) { 701 return; 702 } 703 for(unsigned rdnDex=0; rdnDex<x509Name->numberOfRDNs; rdnDex++) { 704 CSSM_X509_RDN_PTR rdn = &x509Name->RelativeDistinguishedName[rdnDex]; 705 CL_freeX509Rdn(rdn, alloc); 706 } 707 alloc.free(x509Name->RelativeDistinguishedName); 708 memset(x509Name, 0, sizeof(CSSM_X509_NAME)); 709} 710 711void CL_freeX509Rdn( 712 CSSM_X509_RDN_PTR rdn, 713 Allocator &alloc) 714{ 715 if(rdn == NULL) { 716 return; 717 } 718 for(unsigned atvDex=0; atvDex<rdn->numberOfPairs; atvDex++) { 719 CSSM_X509_TYPE_VALUE_PAIR_PTR atv = 720 &rdn->AttributeTypeAndValue[atvDex]; 721 alloc.free(atv->type.Data); 722 alloc.free(atv->value.Data); 723 memset(atv, 0, sizeof(CSSM_X509_TYPE_VALUE_PAIR)); 724 } 725 alloc.free(rdn->AttributeTypeAndValue); 726 memset(rdn, 0, sizeof(CSSM_X509_RDN)); 727} 728 729void CL_freeOtherName( 730 CE_OtherName *cssmOther, 731 Allocator &alloc) 732{ 733 if(cssmOther == NULL) { 734 return; 735 } 736 alloc.free(cssmOther->typeId.Data); 737 alloc.free(cssmOther->value.Data); 738 memset(cssmOther, 0, sizeof(*cssmOther)); 739} 740 741void CL_freeCssmIssuingDistPoint( 742 CE_IssuingDistributionPoint *cssmIdp, 743 Allocator &alloc) 744{ 745 CL_freeCssmDistPointName(cssmIdp->distPointName, alloc); 746} 747 748