/***
 *** Public key info
 *** Format = CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
 ***/
static bool getField_PublicKeyInfo (
	DecodedItem		 	&item,
	unsigned			index,			// which occurrence (0 = first)
	uint32				&numFields,		// RETURNED
	CssmOwnedData		&fieldValue)	// RETURNED
{
	const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
	const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &srcInfo =
		cert.mCert.tbs.subjectPublicKeyInfo;
	if(!tbsGetCheck(srcInfo.subjectPublicKey.Data, index)) {
		return false;
	}

	Allocator &alloc = fieldValue.allocator;
	fieldValue.malloc(sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO));
	CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *dstInfo =
		(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data();

	CL_copySubjPubKeyInfo(srcInfo, true,		// length in bits here
		*dstInfo, false,						// length in bytes
		alloc);

	numFields = 1;
	return true;
}
static void freeField_PublicKeyInfo (
	CssmOwnedData		&fieldValue)
{
	CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *cssmKeyInfo =
		(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data();
	if(cssmKeyInfo == NULL) {
		return;
	}
	Allocator &alloc = fieldValue.allocator;
	CL_freeCssmAlgId(&cssmKeyInfo->algorithm, alloc);
	alloc.free(cssmKeyInfo->subjectPublicKey.Data);
	memset(cssmKeyInfo, 0, sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO));}
/***
 *** SignedCRL
 *** Format: CSSM_X509_SIGNED_CRL (the whole enchilada, parsed)
 ***/
static bool getField_SignedCrl (
	DecodedItem		 	&item,
	unsigned			index,			// which occurrence (0 = first)
	uint32				&numFields,		// RETURNED
	CssmOwnedData		&fieldValue)	// RETURNED
{
	Allocator 			&alloc = fieldValue.allocator;
	
	const DecodedCrl &nssCrl = dynamic_cast<const DecodedCrl &>(item);
	const NSS_TBSCrl &nssTbs = nssCrl.mCrl.tbs;
	fieldValue.malloc(sizeof(CSSM_X509_SIGNED_CRL));
	CSSM_X509_SIGNED_CRL	&cssmCrl = *((CSSM_X509_SIGNED_CRL *)fieldValue.data());

	memset(&cssmCrl, 0, sizeof(CSSM_X509_SIGNED_CRL));
	CSSM_X509_TBS_CERTLIST &cssmTbs = cssmCrl.tbsCertList;

	/* version */
	clAllocCopyData(alloc, nssTbs.version, cssmTbs.version);
	
	/* CSSM_X509_ALGORITHM_IDENTIFIER signature - in TBS and CRL */
	CL_copyAlgId(nssTbs.signature, cssmTbs.signature, alloc);
	CL_copyAlgId(nssCrl.mCrl.signatureAlgorithm, 
			cssmCrl.signature.algorithmIdentifier, alloc);
	
	/* CSSM_X509_NAME issuer */
	CL_nssNameToCssm(nssTbs.issuer, cssmTbs.issuer, alloc);
	
	/* CSSM_X509_TIME thisUpdate, nextUpdate */
	CL_nssTimeToCssm(nssTbs.thisUpdate, cssmTbs.thisUpdate, alloc);
	CL_nssTimeToCssm(nssTbs.nextUpdate, cssmTbs.nextUpdate, alloc);
	
	/* CSSM_X509_REVOKED_CERT_LIST_PTR revokedCertificates */
	if(nssTbs.revokedCerts != NULL) {
		cssmTbs.revokedCertificates = (CSSM_X509_REVOKED_CERT_LIST_PTR)
			alloc.malloc(sizeof(CSSM_X509_REVOKED_CERT_LIST));
		memset(cssmTbs.revokedCertificates, 0, sizeof(CSSM_X509_REVOKED_CERT_LIST));
		nssRevokedListToCssm(nssTbs.revokedCerts,
			cssmTbs.revokedCertificates, alloc);
	}
	
	/* CSSM_X509_EXTENSIONS extensions */
	const DecodedExtensions &decodedExtens = nssCrl.decodedExtens();
	decodedExtens.convertToCdsa(cssmTbs.extensions, alloc);
	
	/* raw signature - stored in bits - note signature.algId set above */
	CSSM_DATA nssSig = nssCrl.mCrl.signature;
	nssSig.Length = (nssSig.Length + 7) / 8;
	clAllocCopyData(alloc, nssSig, cssmCrl.signature.encrypted);
	numFields = 1;
	return true;
}
/*
 * Free the fieldId-specific data referred to by fieldValue->Data.
 */
void DecodedCert::freeCertFieldData(
	const CssmOid		&fieldId,
	CssmOwnedData		&fieldValue)
{
	if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) {
		CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER);
	}
	const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
	if(fieldFuncs->freeFcn != NULL) {
		/* optional - simple cases handled below */
		fieldFuncs->freeFcn(fieldValue);
	}
	fieldValue.reset();
	fieldValue.release();

}
void freeField_SignedCrl (
	CssmOwnedData		&fieldValue)
{
	CSSM_X509_SIGNED_CRL *cssmCrl = 
		(CSSM_X509_SIGNED_CRL *)fieldValue.data();
		
	if(cssmCrl == NULL) {
		return;
	}
	if(fieldValue.length() != sizeof(CSSM_X509_SIGNED_CRL)) {
		CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
	}
	Allocator &alloc = fieldValue.allocator;
	CSSM_X509_TBS_CERTLIST_PTR cssmTbs = &cssmCrl->tbsCertList;
	if(cssmTbs == NULL) {
		CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
	}
	
	/* run down the fields */
	if(cssmTbs->version.Data) {
		alloc.free(cssmTbs->version.Data);
	}

	/* CSSM_X509_ALGORITHM_IDENTIFIER signature - in TBS and CRL */
	CL_freeCssmAlgId(&cssmTbs->signature, alloc);
	CL_freeCssmAlgId(&cssmCrl->signature.algorithmIdentifier, alloc);

	/* issuer, thisUpdate, nextUpdate */
	CL_freeX509Name(&cssmTbs->issuer, alloc);
	CL_freeCssmTime(&cssmTbs->thisUpdate, alloc);
	CL_freeCssmTime(&cssmTbs->nextUpdate, alloc);
	
	/* CSSM_X509_REVOKED_CERT_LIST_PTR revokedCertificates */
	freeCssmRevokedList(cssmTbs->revokedCertificates, alloc);
	alloc.free(cssmTbs->revokedCertificates);
	
	/* CSSM_X509_EXTENSIONS extensions */
	CL_freeCssmExtensions(cssmTbs->extensions, alloc);

	/* raw signature - note signature.algId freed above */
	alloc.free(cssmCrl->signature.encrypted.Data);
	
	memset(cssmCrl, 0, sizeof(CSSM_X509_SIGNED_CRL));
}
static void freeField_PublicKeyStruct (
	CssmOwnedData		&fieldValue)
{
	CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data();
	CL_freeCSSMKey(cssmKey, fieldValue.allocator, false);
}