]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_apple_x509_cl/lib/clNameUtils.cpp
Security-57031.40.6.tar.gz
[apple/security.git] / Security / libsecurity_apple_x509_cl / lib / clNameUtils.cpp
1 /*
2 * Copyright (c) 2003,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 * 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 */
32 static
33 void 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 */
46 void 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 */
72 void 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 */
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 = (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 */
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 = (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
280 void 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
381 void 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
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 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
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], 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 */
581 void 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
592 void 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
603 void 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
634 void 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
651 void 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
671 void 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 */
696 void 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
711 void 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
729 void 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
741 void CL_freeCssmIssuingDistPoint(
742 CE_IssuingDistributionPoint *cssmIdp,
743 Allocator &alloc)
744 {
745 CL_freeCssmDistPointName(cssmIdp->distPointName, alloc);
746 }
747