]> git.saurik.com Git - apple/security.git/blob - AppleX509CL/clNameUtils.cpp
Security-179.tar.gz
[apple/security.git] / AppleX509CL / clNameUtils.cpp
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.h>
26
27 #pragma mark ----- NSS_Name <--> CSSM_X509_NAME -----
28
29 /*
30 * NSS_ATV --> CSSM_X509_TYPE_VALUE_PAIR
31 */
32
33 void CL_nssAtvToCssm(
34 const NSS_ATV &nssObj,
35 CSSM_X509_TYPE_VALUE_PAIR &cssmObj,
36 CssmAllocator &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 */
46 void CL_nssRdnToCssm(
47 const NSS_RDN &nssObj,
48 CSSM_X509_RDN &cssmObj,
49 CssmAllocator &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 */
72 void CL_nssNameToCssm(
73 const NSS_Name &nssObj,
74 CSSM_X509_NAME &cssmObj,
75 CssmAllocator &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 */
101 void 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 */
117 void 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 */
139 void 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
160 void 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 = 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 */
229 void 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 = 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
280 void CL_nssGeneralNameToCssm(
281 NSS_GeneralName &nssObj,
282 CE_GeneralName &cdsaObj,
283 SecNssCoder &coder, // for temp decoding
284 CssmAllocator &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 NSS_GenNameOtherNameTemplate,
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, NSS_NameTemplate, 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
381 void CL_nssGeneralNamesToCssm(
382 const NSS_GeneralNames &nssObj,
383 CE_GeneralNames &cdsaObj,
384 SecNssCoder &coder, // for temp decoding
385 CssmAllocator &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], NSS_GeneralNameTemplate,
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
421 void 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 NSS_OtherNameTemplate, 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 NSS_NameTemplate, 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
548 void 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], NSS_GeneralNameTemplate,
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 */
581 void clCopyOtherName(
582 const CE_OtherName &src,
583 CE_OtherName &dst,
584 CssmAllocator &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
592 void CL_freeAuthorityKeyId(
593 CE_AuthorityKeyID &cdsaObj,
594 CssmAllocator &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
603 void CL_freeCssmGeneralNames(
604 CE_GeneralNames *cdsaObj,
605 CssmAllocator &alloc)
606 {
607 if(cdsaObj == NULL) {
608 return;
609 }
610 for(unsigned i=0; i<cdsaObj->numNames; i++) {
611 /*
612 * Two special cases here.
613 */
614 CE_GeneralName *genName = &cdsaObj->generalName[i];
615 switch(genName->nameType) {
616 case GNT_DirectoryName:
617 if((!genName->berEncoded) && // we're flexible
618 (genName->name.Length ==
619 sizeof(CSSM_X509_NAME))) { // paranoia
620 CL_freeX509Name((CSSM_X509_NAME_PTR)genName->name.Data, alloc);
621 }
622 break;
623
624 case GNT_OtherName:
625 if((!genName->berEncoded) && // we're flexible
626 (genName->name.Length ==
627 sizeof(CE_OtherName))) { // paranoia
628 CE_OtherName *con = (CE_OtherName *)genName->name.Data;
629 CL_freeOtherName(con, alloc);
630 }
631 break;
632 default:
633 break;
634 }
635 /* and always free this */
636 alloc.free(cdsaObj->generalName[i].name.Data);
637 }
638 if(cdsaObj->numNames) {
639 memset(cdsaObj->generalName, 0, cdsaObj->numNames * sizeof(CE_GeneralName));
640 alloc.free(cdsaObj->generalName);
641 }
642 memset(cdsaObj, 0, sizeof(CE_GeneralNames));
643 }
644
645 void CL_freeCssmDistPoints(
646 CE_CRLDistPointsSyntax *cssmDps,
647 CssmAllocator &alloc)
648 {
649 if(cssmDps == NULL) {
650 return;
651 }
652 for(unsigned dex=0; dex<cssmDps->numDistPoints; dex++) {
653 CE_CRLDistributionPoint *cssmDp = &cssmDps->distPoints[dex];
654 if(cssmDp->distPointName) {
655 CL_freeCssmDistPointName(cssmDp->distPointName, alloc);
656 alloc.free(cssmDp->distPointName);
657 }
658 if(cssmDp->crlIssuer) {
659 CL_freeCssmGeneralNames(cssmDp->crlIssuer, alloc);
660 alloc.free(cssmDp->crlIssuer);
661 }
662 }
663 memset(cssmDps->distPoints, 0,
664 cssmDps->numDistPoints * sizeof(CE_CRLDistributionPoint));
665 alloc.free(cssmDps->distPoints);
666 memset(cssmDps, 0, sizeof(*cssmDps));
667 }
668
669 void CL_freeCssmDistPointName(
670 CE_DistributionPointName *cssmDpn,
671 CssmAllocator &alloc)
672 {
673 if(cssmDpn == NULL) {
674 return;
675 }
676 switch(cssmDpn->nameType) {
677 case CE_CDNT_FullName:
678 CL_freeCssmGeneralNames(cssmDpn->fullName, alloc);
679 alloc.free(cssmDpn->fullName);
680 break;
681 case CE_CDNT_NameRelativeToCrlIssuer:
682 CL_freeX509Rdn(cssmDpn->rdn, alloc);
683 alloc.free(cssmDpn->rdn);
684 break;
685 }
686 memset(cssmDpn, 0, sizeof(*cssmDpn));
687 }
688
689 /* free contents of an CSSM_X509_NAME */
690 void CL_freeX509Name(
691 CSSM_X509_NAME_PTR x509Name,
692 CssmAllocator &alloc)
693 {
694 if(x509Name == NULL) {
695 return;
696 }
697 for(unsigned rdnDex=0; rdnDex<x509Name->numberOfRDNs; rdnDex++) {
698 CSSM_X509_RDN_PTR rdn = &x509Name->RelativeDistinguishedName[rdnDex];
699 CL_freeX509Rdn(rdn, alloc);
700 }
701 alloc.free(x509Name->RelativeDistinguishedName);
702 memset(x509Name, 0, sizeof(CSSM_X509_NAME));
703 }
704
705 void CL_freeX509Rdn(
706 CSSM_X509_RDN_PTR rdn,
707 CssmAllocator &alloc)
708 {
709 if(rdn == NULL) {
710 return;
711 }
712 for(unsigned atvDex=0; atvDex<rdn->numberOfPairs; atvDex++) {
713 CSSM_X509_TYPE_VALUE_PAIR_PTR atv =
714 &rdn->AttributeTypeAndValue[atvDex];
715 alloc.free(atv->type.Data);
716 alloc.free(atv->value.Data);
717 memset(atv, 0, sizeof(CSSM_X509_TYPE_VALUE_PAIR));
718 }
719 alloc.free(rdn->AttributeTypeAndValue);
720 memset(rdn, 0, sizeof(CSSM_X509_RDN));
721 }
722
723 void CL_freeOtherName(
724 CE_OtherName *cssmOther,
725 CssmAllocator &alloc)
726 {
727 if(cssmOther == NULL) {
728 return;
729 }
730 alloc.free(cssmOther->typeId.Data);
731 alloc.free(cssmOther->value.Data);
732 memset(cssmOther, 0, sizeof(*cssmOther));
733 }
734
735 void CL_freeCssmIssuingDistPoint(
736 CE_IssuingDistributionPoint *cssmIdp,
737 CssmAllocator &alloc)
738 {
739 CL_freeCssmDistPointName(cssmIdp->distPointName, alloc);
740 }
741