1/*
2 * Copyright (c) 2000-2010 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 * CLCertExtensions.cpp - extensions support. A major component of DecodedCert.
21 *
22 */
23
24#include "DecodedCert.h"
25#include "cldebugging.h"
26#include "CLCertExtensions.h"
27#include "CLFieldsCommon.h"
28#include "clNssUtils.h"
29#include "clNameUtils.h"
30#include <security_utilities/utilities.h>
31#include <Security/oidscert.h>
32#include <Security/oidsattr.h>
33#include <Security/cssmerr.h>
34#include <Security/x509defs.h>
35#include <Security/certextensions.h>
36#include <security_utilities/globalizer.h>
37#include <Security/certExtensionTemplates.h>
38#include <Security/SecAsn1Templates.h>
39
40/***
41 *** get/set/free functions called out from CertFields.cpp
42 ***/
43
44/***
45 *** KeyUsage
46 *** CDSA format 	CE_KeyUsage
47 *** NSS format 	CSSM_DATA, length 2
48 *** OID 			CSSMOID_KeyUsage
49 ***/
50
51void setFieldKeyUsage(
52	DecodedItem	&cert,
53	const CssmData &fieldValue)
54{
55	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
56		false);
57	CE_KeyUsage *cdsaObj = (CE_KeyUsage *)cssmExt->value.parsedValue;
58
59	/* Alloc an NSS-style key usage in cert.coder's memory */
60	SecNssCoder &coder = cert.coder();
61	CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
62	coder.allocItem(*nssObj, 2);
63
64	/* cdsaObj --> nssObj */
65	nssObj->Data[0] = (*cdsaObj) >> 8;
66	nssObj->Data[1] = *cdsaObj;
67
68	/* Adjust length for BIT STRING encoding */
69	clCssmBitStringToNss(*nssObj);
70
71	/* add to mExtensions */
72	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
73		kSecAsn1KeyUsageTemplate);
74}
75
76
77bool getFieldKeyUsage(
78	DecodedItem 		&cert,
79	unsigned			index,			// which occurrence (0 = first)
80	uint32				&numFields,		// RETURNED
81	CssmOwnedData		&fieldValue)
82{
83	const DecodedExten *decodedExt;
84	CSSM_DATA *nssObj;
85	CE_KeyUsage *cdsaObj;
86	bool brtn;
87
88	brtn = cert.GetExtenTop<CSSM_DATA, CE_KeyUsage>(
89		index,
90		numFields,
91		fieldValue.allocator,
92		CSSMOID_KeyUsage,
93		nssObj,
94		cdsaObj,
95		decodedExt);
96	if(!brtn) {
97		return false;
98	}
99
100	/* make a copy - can't modify length in place */
101	CSSM_DATA bitString = *nssObj;
102	clNssBitStringToCssm(bitString);
103	size_t toCopy = bitString.Length;
104	if(toCopy > 2) {
105		/* I hope I never see this... */
106		clErrorLog("getFieldKeyUsage: KeyUsage larger than 2 bytes!");
107		toCopy = 2;
108	}
109	unsigned char bits[2] = {0, 0};
110	memmove(bits, bitString.Data, toCopy);
111	*cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
112
113	/* pass back to caller */
114	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
115	return true;
116}
117
118/***
119 *** Basic Constraints
120 *** CDSA format: 	CE_BasicConstraints
121 *** NSS format 	CE_BasicConstraints
122 *** OID 			CSSMOID_BasicConstraints
123 ***/
124
125void setFieldBasicConstraints(
126	DecodedItem	&cert,
127	const CssmData &fieldValue)
128{
129	CSSM_X509_EXTENSION_PTR cssmExt =
130		verifySetFreeExtension(fieldValue, false);
131	CE_BasicConstraints *cdsaObj =
132		(CE_BasicConstraints *)cssmExt->value.parsedValue;
133
134	/* Alloc an NSS-style BasicConstraints in cert.coder's memory */
135	SecNssCoder &coder = cert.coder();
136	NSS_BasicConstraints *nssObj =
137		(NSS_BasicConstraints *)coder.malloc(sizeof(NSS_BasicConstraints));
138	memset(nssObj, 0, sizeof(*nssObj));
139
140	/* cdsaObj --> nssObj */
141	ArenaAllocator arenaAlloc(coder);
142	clCssmBoolToNss(cdsaObj->cA, nssObj->cA, arenaAlloc);
143	if(cdsaObj->pathLenConstraintPresent) {
144		clIntToData(cdsaObj->pathLenConstraint,
145			nssObj->pathLenConstraint, arenaAlloc);
146	}
147
148	/* add to mExtensions */
149	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
150		kSecAsn1BasicConstraintsTemplate);
151}
152
153
154bool getFieldBasicConstraints(
155	DecodedItem 		&cert,
156	unsigned			index,			// which occurrence (0 = first)
157	uint32				&numFields,		// RETURNED
158	CssmOwnedData		&fieldValue)
159{
160	const DecodedExten *decodedExt;
161	NSS_BasicConstraints *nssObj;
162	CE_BasicConstraints *cdsaObj;
163	bool brtn;
164
165	brtn = cert.GetExtenTop<NSS_BasicConstraints, CE_BasicConstraints>(
166		index,
167		numFields,
168		fieldValue.allocator,
169		CSSMOID_BasicConstraints,
170		nssObj,
171		cdsaObj,
172		decodedExt);
173	if(!brtn) {
174		return false;
175	}
176
177	if(nssObj->cA.Data == NULL) {
178		/* default */
179		cdsaObj->cA = CSSM_FALSE;
180	}
181	else {
182		cdsaObj->cA = clNssBoolToCssm(nssObj->cA);
183	}
184	if(nssObj->pathLenConstraint.Data == NULL) {
185		/* optional */
186		cdsaObj->pathLenConstraintPresent = CSSM_FALSE;
187		cdsaObj->pathLenConstraint = 0;
188	}
189	else {
190		cdsaObj->pathLenConstraintPresent = CSSM_TRUE;
191		cdsaObj->pathLenConstraint = clDataToInt(nssObj->pathLenConstraint);
192	}
193
194	/* pass back to caller */
195	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
196	return true;
197}
198
199/***
200 *** Extended Key Usage
201 *** CDSA format: 	CE_ExtendedKeyUsage
202 *** NSS format: 	NSS_ExtKeyUsage
203 *** OID 			CSSMOID_ExtendedKeyUsage
204 ***/
205void setFieldExtKeyUsage(
206	DecodedItem	&cert,
207	const CssmData &fieldValue)
208{
209	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
210		false);
211	CE_ExtendedKeyUsage *cdsaObj =
212		(CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
213
214	SecNssCoder &coder = cert.coder();
215	NSS_ExtKeyUsage *nssObj =
216		(NSS_ExtKeyUsage *)coder.malloc(sizeof(NSS_ExtKeyUsage));
217	memset(nssObj, 0, sizeof(*nssObj));
218	if(cdsaObj->numPurposes != 0) {
219		nssObj->purposes =
220			(CSSM_OID **)clNssNullArray(cdsaObj->numPurposes, coder);
221	}
222
223	/* cdsaObj --> nssObj, one 'purpose' (OID) at a time */
224	for(unsigned dex=0; dex<cdsaObj->numPurposes; dex++) {
225		nssObj->purposes[dex] = (CSSM_OID *)coder.malloc(sizeof(CSSM_OID));
226		coder.allocCopyItem(cdsaObj->purposes[dex],
227			*nssObj->purposes[dex]);
228	}
229
230	/* add to mExtensions */
231	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
232		kSecAsn1ExtKeyUsageTemplate);
233}
234
235bool getFieldExtKeyUsage(
236	DecodedItem 		&cert,
237	unsigned			index,			// which occurrence (0 = first)
238	uint32				&numFields,		// RETURNED
239	CssmOwnedData		&fieldValue)
240{
241	const DecodedExten *decodedExt;
242	NSS_ExtKeyUsage *nssObj;
243	CE_ExtendedKeyUsage *cdsaObj;
244	bool brtn;
245	Allocator &alloc = fieldValue.allocator;
246
247	brtn = cert.GetExtenTop<NSS_ExtKeyUsage, CE_ExtendedKeyUsage>(
248		index,
249		numFields,
250		alloc,
251		CSSMOID_ExtendedKeyUsage,
252		nssObj,
253		cdsaObj,
254		decodedExt);
255	if(!brtn) {
256		return false;
257	}
258
259	/* nssObj --> cdsaObj, one purpose at a time */
260	unsigned numPurposes = clNssArraySize((const void **)nssObj->purposes);
261	cdsaObj->numPurposes = numPurposes;
262	if(numPurposes) {
263		unsigned len = numPurposes * sizeof(CSSM_OID);
264		cdsaObj->purposes = (CSSM_OID_PTR)alloc.malloc(len);
265		memset(cdsaObj->purposes, 0, len);
266	}
267	for(unsigned dex=0; dex<numPurposes; dex++) {
268		clAllocCopyData(alloc, *nssObj->purposes[dex], cdsaObj->purposes[dex]);
269	}
270
271	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
272	return true;
273}
274
275void freeFieldExtKeyUsage(
276	CssmOwnedData		&fieldValue)
277{
278	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
279	Allocator &alloc = fieldValue.allocator;
280	CE_ExtendedKeyUsage *cdsaObj =
281		(CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
282	unsigned oidDex;
283	for(oidDex=0; oidDex<cdsaObj->numPurposes; oidDex++) {
284		alloc.free(cdsaObj->purposes[oidDex].Data);
285	}
286	alloc.free(cdsaObj->purposes);
287	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
288}
289
290/***
291 *** Subject Key Identifier
292 *** CDSA format: 	CE_SubjectKeyID, which is just a CSSM_DATA
293 *** OID 			CSSMOID_SubjectKeyIdentifier
294 ***/
295
296void setFieldSubjectKeyId(
297	DecodedItem	&cert,
298	const CssmData &fieldValue)
299{
300	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
301		false);
302	CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue;
303	SecNssCoder &coder = cert.coder();
304	CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
305	coder.allocCopyItem(*cdsaObj, *nssObj);
306
307	/* add to mExtensions */
308	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
309		kSecAsn1SubjectKeyIdTemplate);
310}
311
312bool getFieldSubjectKeyId(
313	DecodedItem	 	&cert,
314	unsigned			index,			// which occurrence (0 = first)
315	uint32				&numFields,		// RETURNED
316	CssmOwnedData		&fieldValue)
317{
318	const DecodedExten *decodedExt;
319	CSSM_DATA *nssObj;
320	CE_SubjectKeyID *cdsaObj;
321	bool brtn;
322	Allocator &alloc = fieldValue.allocator;
323
324	brtn = cert.GetExtenTop<CSSM_DATA, CE_SubjectKeyID>(
325		index,
326		numFields,
327		alloc,
328		CSSMOID_SubjectKeyIdentifier,
329		nssObj,
330		cdsaObj,
331		decodedExt);
332	if(!brtn) {
333		return false;
334	}
335
336	/* if this fails, we're out of sync with nssExtenInfo[] in
337	 * CLFieldsCommon.cpp */
338	assert(nssObj != NULL);
339	clAllocCopyData(alloc, *nssObj, *cdsaObj);
340	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
341	return true;
342}
343
344void freeFieldSubjectKeyId (
345	CssmOwnedData		&fieldValue)
346{
347	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
348	Allocator &alloc = fieldValue.allocator;
349	CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue;
350	alloc.free(cdsaObj->Data);
351	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
352}
353
354/***
355 *** Authority Key Identifier
356 *** CDSA format: 	CE_AuthorityKeyID
357 *** NSS format: 	NSS_AuthorityKeyId
358 *** OID 			CSSMOID_AuthorityKeyIdentifier
359 ***/
360
361void setFieldAuthorityKeyId(
362	DecodedItem	&cert,
363	const CssmData &fieldValue)
364{
365	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
366		false);
367	CE_AuthorityKeyID *cdsaObj =
368		(CE_AuthorityKeyID *)cssmExt->value.parsedValue;
369
370	/* Alloc an NSS-style AuthorityKeyId in cert.coder's memory */
371	SecNssCoder &coder = cert.coder();
372	NSS_AuthorityKeyId *nssObj =
373		(NSS_AuthorityKeyId *)coder.malloc(sizeof(NSS_AuthorityKeyId));
374	memset(nssObj, 0, sizeof(*nssObj));
375
376	/* convert caller's CDSA-style CE_AuthorityKeyID to NSS */
377	CL_cssmAuthorityKeyIdToNss(*cdsaObj, *nssObj, coder);
378
379	/* add to mExtensions */
380	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
381		kSecAsn1AuthorityKeyIdTemplate);
382}
383
384bool getFieldAuthorityKeyId(
385	DecodedItem		 	&cert,
386	unsigned			index,			// which occurrence (0 = first)
387	uint32				&numFields,		// RETURNED
388	CssmOwnedData		&fieldValue)
389{
390	const DecodedExten *decodedExt;
391	NSS_AuthorityKeyId *nssObj;
392	CE_AuthorityKeyID *cdsaObj;
393	bool brtn;
394	Allocator &alloc = fieldValue.allocator;
395
396	brtn = cert.GetExtenTop<NSS_AuthorityKeyId, CE_AuthorityKeyID>(
397		index,
398		numFields,
399		alloc,
400		CSSMOID_AuthorityKeyIdentifier,
401		nssObj,
402		cdsaObj,
403		decodedExt);
404	if(!brtn) {
405		return false;
406	}
407	assert(nssObj != NULL);
408
409	/* nssObj --> cdsaObj */
410	CL_nssAuthorityKeyIdToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
411
412	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
413	return true;
414}
415
416void freeFieldAuthorityKeyId (
417	CssmOwnedData		&fieldValue)
418{
419	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
420	Allocator &alloc = fieldValue.allocator;
421	CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
422	CL_freeAuthorityKeyId(*cdsaObj, alloc);
423	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
424}
425
426/***
427 *** Subject/Issuer alternate name
428 *** CDSA Format:	CE_GeneralNames
429 *** NSS format:	NSS_GeneralNames
430 *** OID: 			CSSMOID_SubjectAltName, CSSMOID_IssuerAltName
431 ***/
432void setFieldSubjIssuerAltName(
433	DecodedItem	&cert,
434	const CssmData &fieldValue)
435{
436	CSSM_X509_EXTENSION_PTR cssmExt =
437		verifySetFreeExtension(fieldValue, false);
438	CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
439
440	/* Alloc an NSS-style GeneralNames in cert.coder's memory */
441	SecNssCoder &coder = cert.coder();
442	NSS_GeneralNames *nssObj =
443		(NSS_GeneralNames *)coder.malloc(sizeof(NSS_GeneralNames));
444	memset(nssObj, 0, sizeof(*nssObj));
445
446	/* cdsaObj --> nssObj */
447	CL_cssmGeneralNamesToNss(*cdsaObj, *nssObj, coder);
448
449	/* add to mExtensions */
450	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
451		kSecAsn1GeneralNamesTemplate);
452}
453
454bool getFieldSubjAltName(
455	DecodedItem 		&cert,
456	unsigned			index,			// which occurrence (0 = first)
457	uint32				&numFields,		// RETURNED
458	CssmOwnedData		&fieldValue)
459{
460	const DecodedExten *decodedExt;
461	NSS_GeneralNames *nssObj;
462	CE_GeneralNames *cdsaObj;
463	bool brtn;
464
465	brtn = cert.GetExtenTop<NSS_GeneralNames, CE_GeneralNames>(
466		index,
467		numFields,
468		fieldValue.allocator,
469		CSSMOID_SubjectAltName,
470		nssObj,
471		cdsaObj,
472		decodedExt);
473	if(!brtn) {
474		return false;
475	}
476	CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj,
477		cert.coder(), fieldValue.allocator);
478	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
479	return true;
480}
481
482bool getFieldIssuerAltName(
483	DecodedItem 		&cert,
484	unsigned			index,			// which occurrence (0 = first)
485	uint32				&numFields,		// RETURNED
486	CssmOwnedData		&fieldValue)
487{
488	const DecodedExten *decodedExt;
489	NSS_GeneralNames *nssObj;
490	CE_GeneralNames *cdsaObj;
491	bool brtn;
492
493	brtn = cert.GetExtenTop<NSS_GeneralNames, CE_GeneralNames>(
494		index,
495		numFields,
496		fieldValue.allocator,
497		CSSMOID_IssuerAltName,
498		nssObj,
499		cdsaObj,
500		decodedExt);
501	if(!brtn) {
502		return false;
503	}
504	CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj,
505		cert.coder(), fieldValue.allocator);
506	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
507	return true;
508}
509
510void freeFieldSubjIssuerAltName (
511	CssmOwnedData		&fieldValue)
512{
513	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
514	Allocator &alloc = fieldValue.allocator;
515	CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
516	CL_freeCssmGeneralNames(cdsaObj, alloc);
517	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
518}
519
520/***
521 *** Certificate Policies
522 *** CDSA Format:	CE_CertPolicies
523 *** NSS format :	NSS_CertPolicies
524 *** OID: 			CSSMOID_CertificatePolicies
525 ***/
526
527#define MAX_IA5_NAME_SIZE	1024
528
529void setFieldCertPolicies(
530	DecodedItem	&cert,
531	const CssmData &fieldValue)
532{
533	CSSM_X509_EXTENSION_PTR cssmExt =
534		verifySetFreeExtension(fieldValue, false);
535	SecNssCoder &coder = cert.coder();
536	NSS_CertPolicies *nssObj =
537		(NSS_CertPolicies *)coder.malloc(sizeof(NSS_CertPolicies));
538	memset(nssObj, 0, sizeof(NSS_CertPolicies));
539	CE_CertPolicies *cdsaObj =
540		(CE_CertPolicies *)cssmExt->value.parsedValue;
541
542	if(cdsaObj->numPolicies) {
543		nssObj->policies =
544			(NSS_PolicyInformation **)clNssNullArray(
545				cdsaObj->numPolicies, coder);
546	}
547	for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
548		CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
549		NSS_PolicyInformation *nPolInfo = (NSS_PolicyInformation *)
550			coder.malloc(sizeof(NSS_PolicyInformation));
551		memset(nPolInfo, 0, sizeof(*nPolInfo));
552		nssObj->policies[polDex] = nPolInfo;
553
554		coder.allocCopyItem(cPolInfo->certPolicyId, nPolInfo->certPolicyId);
555
556		unsigned numQual = cPolInfo->numPolicyQualifiers;
557		if(numQual != 0) {
558			nPolInfo->policyQualifiers =
559				(NSS_PolicyQualifierInfo **)clNssNullArray(numQual,
560					coder);
561		}
562		for(unsigned qualDex=0; qualDex<numQual; qualDex++) {
563			CE_PolicyQualifierInfo *cQualInfo =
564				&cPolInfo->policyQualifiers[qualDex];
565			NSS_PolicyQualifierInfo *nQualInfo =
566				(NSS_PolicyQualifierInfo *)coder.malloc(
567					sizeof(NSS_PolicyQualifierInfo));
568			memset(nQualInfo, 0, sizeof(NSS_PolicyQualifierInfo));
569			nPolInfo->policyQualifiers[qualDex] = nQualInfo;
570
571			/*
572			 * OK we're at the lowest level.
573			 * policyQualifierId == id_qt_cps: qualifier is
574			 * an IA5 string, incoming data is its contents.
575			 * Else incoming data is an encoded blob we pass on directly.
576			 */
577			coder.allocCopyItem(cQualInfo->policyQualifierId,
578				nQualInfo->policyQualifierId);
579
580			if(clCompareCssmData(&cQualInfo->policyQualifierId,
581					&CSSMOID_QT_CPS)) {
582				if(coder.encodeItem(&cQualInfo->qualifier,
583						kSecAsn1IA5StringTemplate,
584						nQualInfo->qualifier)) {
585					clErrorLog("setFieldCertPOlicies: IA5 encode error\n");
586					CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
587				}
588			}
589			else {
590				/* uninterpreted, copy over directly */
591				coder.allocCopyItem(cQualInfo->qualifier,
592					nQualInfo->qualifier);
593			}
594		}	/* for each qualifier */
595	}	/* for each policy */
596
597	/* add to mExtensions */
598	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
599		kSecAsn1CertPoliciesTemplate);
600}
601
602bool getFieldCertPolicies(
603	DecodedItem 		&cert,
604	unsigned			index,			// which occurrence (0 = first)
605	uint32				&numFields,		// RETURNED
606	CssmOwnedData		&fieldValue)
607{
608	const DecodedExten *decodedExt;
609	NSS_CertPolicies *nssObj;
610	CE_CertPolicies *cdsaObj;
611	bool brtn;
612	Allocator &alloc = fieldValue.allocator;
613	brtn = cert.GetExtenTop<NSS_CertPolicies, CE_CertPolicies>(
614		index,
615		numFields,
616		fieldValue.allocator,
617		CSSMOID_CertificatePolicies,
618		nssObj,
619		cdsaObj,
620		decodedExt);
621	if(!brtn) {
622		return false;
623	}
624	assert(nssObj != NULL);
625
626	memset(cdsaObj, 0, sizeof(*cdsaObj));
627	cdsaObj->numPolicies =
628		clNssArraySize((const void **)nssObj->policies);
629	unsigned sz = cdsaObj->numPolicies * sizeof(CE_PolicyInformation);
630	if(sz) {
631		cdsaObj->policies = (CE_PolicyInformation *)alloc.malloc(sz);
632		memset(cdsaObj->policies, 0, sz);
633	}
634
635	for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
636		CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
637		NSS_PolicyInformation *nPolInfo = nssObj->policies[polDex];
638		clAllocCopyData(alloc, nPolInfo->certPolicyId,
639			cPolInfo->certPolicyId);
640		if(nPolInfo->policyQualifiers == NULL) {
641			continue;
642		}
643
644		cPolInfo->numPolicyQualifiers =
645			clNssArraySize((const void **)nPolInfo->policyQualifiers);
646		sz = cPolInfo->numPolicyQualifiers *
647			 sizeof(CE_PolicyQualifierInfo);
648		cPolInfo->policyQualifiers = (CE_PolicyQualifierInfo *)
649			alloc.malloc(sz);
650		memset(cPolInfo->policyQualifiers, 0, sz);
651
652		for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers;
653				qualDex++) {
654			NSS_PolicyQualifierInfo *nQualInfo =
655				nPolInfo->policyQualifiers[qualDex];
656			CE_PolicyQualifierInfo *cQualInfo =
657				&cPolInfo->policyQualifiers[qualDex];
658
659			/*
660			 * leaf.
661			 * policyQualifierId == CSSMOID_QT_CPS :
662			 *  		IA5String - decode and return contents.
663			 * Else return whole thing.
664			 */
665			clAllocCopyData(alloc, nQualInfo->policyQualifierId,
666				cQualInfo->policyQualifierId);
667			CSSM_DATA toCopy = nQualInfo->qualifier;
668			if(clCompareCssmData(&nQualInfo->policyQualifierId,
669						&CSSMOID_QT_CPS)) {
670				/* decode as IA5String to temp memory */
671				toCopy.Data = NULL;
672				toCopy.Length = 0;
673				if(cert.coder().decodeItem(nQualInfo->qualifier,
674						kSecAsn1IA5StringTemplate,
675						&toCopy)) {
676					clErrorLog("***getCertPolicies: bad IA5String!\n");
677					CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
678				}
679			}
680			/* else copy out nQualInfo->qualifier */
681			clAllocCopyData(alloc, toCopy, cQualInfo->qualifier);
682		}	/* for each qualifier */
683	}		/* for each policy info */
684	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
685	return true;
686}
687
688void freeFieldCertPolicies (
689	CssmOwnedData		&fieldValue)
690{
691	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
692	Allocator &alloc = fieldValue.allocator;
693	CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue;
694	for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
695		CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
696		alloc.free(cPolInfo->certPolicyId.Data);
697		for(unsigned qualDex=0;
698		             qualDex<cPolInfo->numPolicyQualifiers;
699					 qualDex++) {
700			CE_PolicyQualifierInfo *cQualInfo =
701				&cPolInfo->policyQualifiers[qualDex];
702			alloc.free(cQualInfo->policyQualifierId.Data);
703			alloc.free(cQualInfo->qualifier.Data);
704		}
705		alloc.free(cPolInfo->policyQualifiers);
706	}
707	alloc.free(cdsaObj->policies);
708	freeFieldExtenCommon(cssmExt, alloc);	// frees extnId, parsedValue,
709											//    BERvalue
710}
711
712/***
713 *** Netscape cert type
714 *** CDSA Format:	CE_NetscapeCertType (a uint16)
715 *** NSS format 	CSSM_DATA, length 2
716 *** OID: 			CSSMOID_NetscapeCertType
717 ***/
718void setFieldNetscapeCertType(
719	DecodedItem	&cert,
720	const CssmData &fieldValue)
721{
722	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
723		false);
724	CE_NetscapeCertType *cdsaObj =
725		(CE_NetscapeCertType *)cssmExt->value.parsedValue;
726
727	/* Alloc an NSS-style key usage in cert.coder's memory */
728	SecNssCoder &coder = cert.coder();
729	CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
730	coder.allocItem(*nssObj, 2);
731
732	/* cdsaObj --> nssObj */
733	nssObj->Data[0] = (*cdsaObj) >> 8;
734	nssObj->Data[1] = *cdsaObj;
735
736	/* Adjust length for BIT STRING encoding */
737	clCssmBitStringToNss(*nssObj);
738
739	/* add to mExtensions */
740	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
741		kSecAsn1NetscapeCertTypeTemplate);
742}
743
744bool getFieldNetscapeCertType(
745	DecodedItem 		&cert,
746	unsigned			index,			// which occurrence (0 = first)
747	uint32				&numFields,		// RETURNED
748	CssmOwnedData		&fieldValue)
749{
750	const DecodedExten *decodedExt;
751	CSSM_DATA *nssObj;
752	CE_NetscapeCertType *cdsaObj;
753	bool brtn;
754
755	brtn = cert.GetExtenTop<CSSM_DATA, CE_NetscapeCertType>(
756		index,
757		numFields,
758		fieldValue.allocator,
759		CSSMOID_NetscapeCertType,
760		nssObj,
761		cdsaObj,
762		decodedExt);
763	if(!brtn) {
764		return false;
765	}
766
767	/* make a copy - can't modify length in place */
768	CSSM_DATA bitString = *nssObj;
769	clNssBitStringToCssm(bitString);
770	size_t toCopy = bitString.Length;
771	if(toCopy > 2) {
772		/* I hope I never see this... */
773		clErrorLog("getFieldKeyUsage: CertType larger than 2 bytes!");
774		toCopy = 2;
775	}
776	unsigned char bits[2] = {0, 0};
777	memmove(bits, bitString.Data, toCopy);
778	*cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
779
780	/* pass back to caller */
781	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
782	return true;
783}
784
785/***
786 *** CRL Distribution points
787 *** CDSA Format:	CE_CRLDistPointsSyntax
788 *** NSS format:	NSS_CRLDistributionPoints
789 *** OID: 			CSSMOID_CrlDistributionPoints
790 ***/
791void setFieldCrlDistPoints(
792	DecodedItem	&cert,
793	const CssmData &fieldValue)
794{
795	CSSM_X509_EXTENSION_PTR cssmExt =
796		verifySetFreeExtension(fieldValue, false);
797	CE_CRLDistPointsSyntax *cdsaObj =
798		(CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue;
799	SecNssCoder &coder = cert.coder();
800	NSS_CRLDistributionPoints *nssObj =
801		(NSS_CRLDistributionPoints *)coder.malloc(
802				sizeof(NSS_CRLDistributionPoints));
803
804	CL_cssmDistPointsToNss(*cdsaObj, *nssObj, coder);
805	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
806		kSecAsn1CRLDistributionPointsTemplate);
807}
808
809bool getFieldCrlDistPoints(
810	DecodedItem 		&cert,
811	unsigned			index,			// which occurrence (0 = first)
812	uint32				&numFields,		// RETURNED
813	CssmOwnedData		&fieldValue)
814{
815	const DecodedExten *decodedExt;
816	NSS_CRLDistributionPoints *nssObj;
817	CE_CRLDistPointsSyntax *cdsaObj;
818	bool brtn;
819	Allocator &alloc = fieldValue.allocator;
820
821	brtn = cert.GetExtenTop<NSS_CRLDistributionPoints,
822			CE_CRLDistPointsSyntax>(
823		index,
824		numFields,
825		alloc,
826		CSSMOID_CrlDistributionPoints,
827		nssObj,
828		cdsaObj,
829		decodedExt);
830	if(!brtn) {
831		return false;
832	}
833	assert(nssObj != NULL);
834	CL_nssDistPointsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
835	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
836	return true;
837}
838
839void freeFieldCrlDistPoints (
840	CssmOwnedData		&fieldValue)
841{
842	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
843	Allocator &alloc = fieldValue.allocator;
844	CE_CRLDistPointsSyntax *cdsaObj =
845		(CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue;
846	CL_freeCssmDistPoints(cdsaObj, alloc);
847	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
848}
849
850/***
851 *** {Subject,Authority}InfoAccess
852 ***
853 *** CDSA Format:	CE_AuthorityInfoAccess
854 *** NSS format:	NSS_AuthorityInfoAccess
855 *** OID: 			CSSMOID_AuthorityInfoAccess, CSSMOID_SubjectInfoAccess
856 ***/
857void setFieldAuthInfoAccess(
858	DecodedItem	&cert,
859	const CssmData &fieldValue)
860{
861	CSSM_X509_EXTENSION_PTR cssmExt =
862		verifySetFreeExtension(fieldValue, false);
863	CE_AuthorityInfoAccess *cdsaObj =
864		(CE_AuthorityInfoAccess *)cssmExt->value.parsedValue;
865	SecNssCoder &coder = cert.coder();
866	NSS_AuthorityInfoAccess *nssObj =
867		(NSS_AuthorityInfoAccess *)coder.malloc(
868				sizeof(NSS_AuthorityInfoAccess));
869
870	CL_cssmInfoAccessToNss(*cdsaObj, *nssObj, coder);
871	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
872		kSecAsn1AuthorityInfoAccessTemplate);
873}
874
875bool getFieldAuthInfoAccess(
876	DecodedItem 		&cert,
877	unsigned			index,			// which occurrence (0 = first)
878	uint32				&numFields,		// RETURNED
879	CssmOwnedData		&fieldValue)
880{
881	const DecodedExten *decodedExt;
882	NSS_AuthorityInfoAccess *nssObj;
883	CE_AuthorityInfoAccess *cdsaObj;
884	bool brtn;
885	Allocator &alloc = fieldValue.allocator;
886
887	brtn = cert.GetExtenTop<NSS_AuthorityInfoAccess,
888			CE_AuthorityInfoAccess>(
889		index,
890		numFields,
891		alloc,
892		CSSMOID_AuthorityInfoAccess,
893		nssObj,
894		cdsaObj,
895		decodedExt);
896	if(!brtn) {
897		return false;
898	}
899	assert(nssObj != NULL);
900	CL_infoAccessToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
901	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
902	return true;
903}
904
905bool getFieldSubjInfoAccess(
906	DecodedItem 		&cert,
907	unsigned			index,			// which occurrence (0 = first)
908	uint32				&numFields,		// RETURNED
909	CssmOwnedData		&fieldValue)
910{
911	const DecodedExten *decodedExt;
912	NSS_AuthorityInfoAccess *nssObj;
913	CE_AuthorityInfoAccess *cdsaObj;
914	bool brtn;
915	Allocator &alloc = fieldValue.allocator;
916
917	brtn = cert.GetExtenTop<NSS_AuthorityInfoAccess,
918			CE_AuthorityInfoAccess>(
919		index,
920		numFields,
921		alloc,
922		CSSMOID_SubjectInfoAccess,
923		nssObj,
924		cdsaObj,
925		decodedExt);
926	if(!brtn) {
927		return false;
928	}
929	assert(nssObj != NULL);
930	CL_infoAccessToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
931	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
932	return true;
933}
934
935void freeFieldInfoAccess (
936	CssmOwnedData		&fieldValue)
937{
938	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
939	Allocator &alloc = fieldValue.allocator;
940	CE_AuthorityInfoAccess *cdsaObj =
941		(CE_AuthorityInfoAccess *)cssmExt->value.parsedValue;
942	CL_freeInfoAccess(*cdsaObj, alloc);
943	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
944
945}
946
947/***
948 *** Qualfied Cert Statements
949 ***
950 *** CDSA Format:	CE_QC_Statements
951 *** NSS format:	NSS_QC_Statements
952 *** OID: 			CSSMOID_QC_Statements
953 ***/
954void setFieldQualCertStatements(
955	DecodedItem	&cert,
956	const CssmData &fieldValue)
957{
958	CSSM_X509_EXTENSION_PTR cssmExt =
959		verifySetFreeExtension(fieldValue, false);
960	CE_QC_Statements *cdsaObj =
961		(CE_QC_Statements *)cssmExt->value.parsedValue;
962	SecNssCoder &coder = cert.coder();
963	NSS_QC_Statements *nssObj =
964		(NSS_QC_Statements *)coder.malloc(
965				sizeof(NSS_QC_Statements));
966
967	CL_cssmQualCertStatementsToNss(*cdsaObj, *nssObj, coder);
968	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
969		kSecAsn1QC_StatementsTemplate);
970}
971
972bool getFieldQualCertStatements(
973	DecodedItem 		&cert,
974	unsigned			index,			// which occurrence (0 = first)
975	uint32				&numFields,		// RETURNED
976	CssmOwnedData		&fieldValue)
977{
978	const DecodedExten *decodedExt;
979	NSS_QC_Statements *nssObj;
980	CE_QC_Statements *cdsaObj;
981	bool brtn;
982	Allocator &alloc = fieldValue.allocator;
983
984	brtn = cert.GetExtenTop<NSS_QC_Statements,
985			CE_QC_Statements>(
986		index,
987		numFields,
988		alloc,
989		CSSMOID_QC_Statements,
990		nssObj,
991		cdsaObj,
992		decodedExt);
993	if(!brtn) {
994		return false;
995	}
996	assert(nssObj != NULL);
997	CL_qualCertStatementsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
998	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
999	return true;
1000}
1001
1002void freeFieldQualCertStatements(
1003	CssmOwnedData		&fieldValue)
1004{
1005	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1006	Allocator &alloc = fieldValue.allocator;
1007	CE_QC_Statements *cdsaObj =
1008		(CE_QC_Statements *)cssmExt->value.parsedValue;
1009	CL_freeQualCertStatements(*cdsaObj, alloc);
1010	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
1011}
1012
1013/***
1014 *** Name Constraints
1015 *** CDSA Format:	CE_NameConstraints
1016 *** NSS format:	NSS_NameConstraints
1017 *** OID: 			CSSMOID_NameConstraints
1018 ***/
1019void setFieldNameConstraints(
1020	DecodedItem	&cert,
1021	const CssmData &fieldValue)
1022{
1023	CSSM_X509_EXTENSION_PTR cssmExt =
1024		verifySetFreeExtension(fieldValue, false);
1025	CE_NameConstraints *cdsaObj =
1026		(CE_NameConstraints *)cssmExt->value.parsedValue;
1027	SecNssCoder &coder = cert.coder();
1028	NSS_NameConstraints *nssObj =
1029		(NSS_NameConstraints *)coder.malloc(
1030				sizeof(NSS_NameConstraints));
1031	CL_cssmNameConstraintsToNss(*cdsaObj, *nssObj, coder);
1032	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
1033		kSecAsn1NameConstraintsTemplate);
1034}
1035
1036bool getFieldNameConstraints(
1037	DecodedItem 		&cert,
1038	unsigned			index,			// which occurrence (0 = first)
1039	uint32				&numFields,		// RETURNED
1040	CssmOwnedData		&fieldValue)
1041{
1042	const DecodedExten *decodedExt;
1043	NSS_NameConstraints *nssObj;
1044	CE_NameConstraints *cdsaObj;
1045	bool brtn;
1046	Allocator &alloc = fieldValue.allocator;
1047
1048	brtn = cert.GetExtenTop<NSS_NameConstraints,
1049			CE_NameConstraints>(
1050		index,
1051		numFields,
1052		alloc,
1053		CSSMOID_NameConstraints,
1054		nssObj,
1055		cdsaObj,
1056		decodedExt);
1057	if(!brtn) {
1058		return false;
1059	}
1060	assert(nssObj != NULL);
1061	CL_nssNameConstraintsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
1062	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1063	return true;
1064}
1065
1066void freeFieldNameConstraints (
1067	CssmOwnedData		&fieldValue)
1068{
1069	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1070	Allocator &alloc = fieldValue.allocator;
1071	CE_NameConstraints *cdsaObj =
1072		(CE_NameConstraints *)cssmExt->value.parsedValue;
1073	CL_freeCssmNameConstraints(cdsaObj, alloc);
1074	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
1075}
1076
1077/***
1078 *** Policy Mappings
1079 *** CDSA Format:	CE_PolicyMappings
1080 *** NSS format:	NSS_PolicyMappings
1081 *** OID: 			CSSMOID_PolicyMappings
1082 ***/
1083void setFieldPolicyMappings(
1084	DecodedItem	&cert,
1085	const CssmData &fieldValue)
1086{
1087	CSSM_X509_EXTENSION_PTR cssmExt =
1088		verifySetFreeExtension(fieldValue, false);
1089	CE_PolicyMappings *cdsaObj =
1090		(CE_PolicyMappings *)cssmExt->value.parsedValue;
1091	SecNssCoder &coder = cert.coder();
1092	NSS_PolicyMappings *nssObj =
1093		(NSS_PolicyMappings *)coder.malloc(
1094				sizeof(NSS_PolicyMappings));
1095	CL_cssmPolicyMappingsToNss(*cdsaObj, *nssObj, coder);
1096	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
1097		kSecAsn1PolicyMappingsTemplate);
1098}
1099
1100bool getFieldPolicyMappings(
1101	DecodedItem 		&cert,
1102	unsigned			index,			// which occurrence (0 = first)
1103	uint32				&numFields,		// RETURNED
1104	CssmOwnedData		&fieldValue)
1105{
1106	const DecodedExten *decodedExt;
1107	NSS_PolicyMappings *nssObj;
1108	CE_PolicyMappings *cdsaObj;
1109	bool brtn;
1110	Allocator &alloc = fieldValue.allocator;
1111
1112	brtn = cert.GetExtenTop<NSS_PolicyMappings,
1113			CE_PolicyMappings>(
1114		index,
1115		numFields,
1116		alloc,
1117		CSSMOID_PolicyMappings,
1118		nssObj,
1119		cdsaObj,
1120		decodedExt);
1121	if(!brtn) {
1122		return false;
1123	}
1124	assert(nssObj != NULL);
1125	CL_nssPolicyMappingsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
1126	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1127	return true;
1128}
1129
1130void freeFieldPolicyMappings (
1131	CssmOwnedData		&fieldValue)
1132{
1133	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1134	Allocator &alloc = fieldValue.allocator;
1135	CE_PolicyMappings *cdsaObj =
1136		(CE_PolicyMappings *)cssmExt->value.parsedValue;
1137	CL_freeCssmPolicyMappings(cdsaObj, alloc);
1138	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
1139}
1140
1141/***
1142 *** Policy Constraints
1143 *** CDSA Format:	CE_PolicyConstraints
1144 *** NSS format:	NSS_PolicyConstraints
1145 *** OID: 			CSSMOID_PolicyConstraints
1146 ***/
1147void setFieldPolicyConstraints(
1148	DecodedItem	&cert,
1149	const CssmData &fieldValue)
1150{
1151	CSSM_X509_EXTENSION_PTR cssmExt =
1152		verifySetFreeExtension(fieldValue, false);
1153	CE_PolicyConstraints *cdsaObj =
1154		(CE_PolicyConstraints *)cssmExt->value.parsedValue;
1155	SecNssCoder &coder = cert.coder();
1156	NSS_PolicyConstraints *nssObj =
1157		(NSS_PolicyConstraints *)coder.malloc(
1158				sizeof(NSS_PolicyConstraints));
1159	CL_cssmPolicyConstraintsToNss(cdsaObj, nssObj, coder);
1160	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
1161		kSecAsn1PolicyConstraintsTemplate);
1162}
1163
1164bool getFieldPolicyConstraints(
1165	DecodedItem 		&cert,
1166	unsigned			index,			// which occurrence (0 = first)
1167	uint32				&numFields,		// RETURNED
1168	CssmOwnedData		&fieldValue)
1169{
1170	const DecodedExten *decodedExt;
1171	NSS_PolicyConstraints *nssObj;
1172	CE_PolicyConstraints *cdsaObj;
1173	bool brtn;
1174	Allocator &alloc = fieldValue.allocator;
1175
1176	brtn = cert.GetExtenTop<NSS_PolicyConstraints,
1177			CE_PolicyConstraints>(
1178		index,
1179		numFields,
1180		alloc,
1181		CSSMOID_PolicyConstraints,
1182		nssObj,
1183		cdsaObj,
1184		decodedExt);
1185	if(!brtn) {
1186		return false;
1187	}
1188	assert(nssObj != NULL);
1189	CL_nssPolicyConstraintsToCssm(nssObj, cdsaObj, cert.coder(), alloc);
1190	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1191	return true;
1192}
1193
1194void freeFieldPolicyConstraints (
1195	CssmOwnedData		&fieldValue)
1196{
1197	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1198	Allocator &alloc = fieldValue.allocator;
1199	CE_PolicyConstraints *cdsaObj =
1200		(CE_PolicyConstraints *)cssmExt->value.parsedValue;
1201	CL_freeCssmPolicyConstraints(cdsaObj, alloc);
1202	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
1203}
1204
1205/***
1206 *** Inhibit Any Policy
1207 *** CDSA Format:	CE_InhibitAnyPolicy (an integer)
1208 *** NSS format:	CSSM_DATA, sizeof(uint32)
1209 *** OID: 			CSSMOID_InhibitAnyPolicy
1210 ***/
1211void setFieldInhibitAnyPolicy(
1212	DecodedItem	&cert,
1213	const CssmData &fieldValue)
1214{
1215	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
1216		false);
1217	CE_InhibitAnyPolicy *cdsaObj =
1218		(CE_InhibitAnyPolicy *)cssmExt->value.parsedValue;
1219
1220	/* Alloc in cert.coder's memory */
1221	SecNssCoder &coder = cert.coder();
1222	CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
1223	coder.allocItem(*nssObj, sizeof(uint32));
1224
1225	/* cdsaObj --> nssObj */
1226	nssObj->Data[0] = (*cdsaObj) >> 24;
1227	nssObj->Data[1] = (*cdsaObj) >> 16;
1228	nssObj->Data[2] = (*cdsaObj) >> 8;
1229	nssObj->Data[3] = *cdsaObj;
1230
1231	/* add to mExtensions */
1232	cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
1233		kSecAsn1IntegerTemplate);
1234}
1235
1236bool getFieldInhibitAnyPolicy(
1237	DecodedItem 		&cert,
1238	unsigned			index,			// which occurrence (0 = first)
1239	uint32				&numFields,		// RETURNED
1240	CssmOwnedData		&fieldValue)
1241{
1242	const DecodedExten *decodedExt;
1243	CSSM_DATA *nssObj;
1244	CE_InhibitAnyPolicy *cdsaObj;
1245	bool brtn;
1246
1247	brtn = cert.GetExtenTop<CSSM_DATA, CE_InhibitAnyPolicy>(
1248		index,
1249		numFields,
1250		fieldValue.allocator,
1251		CSSMOID_InhibitAnyPolicy,
1252		nssObj,
1253		cdsaObj,
1254		decodedExt);
1255	if(!brtn) {
1256		return false;
1257	}
1258
1259	*cdsaObj = *(nssObj->Data); //%%%FIXME check this
1260
1261	/* pass back to caller */
1262	getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1263	return true;
1264}
1265
1266