DecodedExten::DecodedExten(
	const CSSM_OID 	&extnId,	// copied
	bool			critical,
	void			*nssObj,	// NSS_KeyUsage, NSS_BasicConstraints, 
								//   etc. NOT COPIED, exists in same
								//   memory space as coder
	bool			berEncoded,	// indicates unknown extension which we
								// do not BER-decode when parsing a cert
	const SecAsn1Template *templ,	// to decode/encode if !berEncoded
	SecNssCoder		&coder,			// all local allocs from here
	const CSSM_DATA	*rawExtn)	// NSS_CertExtension.value, copied to
								//   mRawExtn
	: mCritical(critical),
	  mNssObj(nssObj),
	  mBerEncoded(berEncoded),
	  mTempl(templ),
	  mCoder(coder),
	  mRawExtn(NULL)
{
	coder.allocCopyItem(extnId, mExtnId);
	if(rawExtn) {
		mRawExtn = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
		coder.allocCopyItem(*rawExtn, *mRawExtn);
	}
}
示例#2
0
/* 
 * Convert a CSSM_KEY to a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO. The
 * CSSM key must be in raw format and with a specific blob format.
 *  	-- RSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_PKCS1
 * 		-- DSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509
 * 		-- ECDSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509
 */
void CL_CSSMKeyToSubjPubKeyInfoNSS(
	const CSSM_KEY 						&cssmKey,
	CSSM_X509_SUBJECT_PUBLIC_KEY_INFO	&nssKeyInfo,
	SecNssCoder							&coder)
{
	const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
	if(hdr.BlobType != CSSM_KEYBLOB_RAW) {
		clErrorLog("CL SetField: must specify RAW key blob\n");
		CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
	}
	memset(&nssKeyInfo, 0, sizeof(nssKeyInfo));
	
	/* algorithm and format dependent from here... */
	switch(hdr.AlgorithmId) {
		case CSSM_ALGID_RSA:
			if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
				clErrorLog("CL SetField: RSA key must be in PKCS1 format\n");
				CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
			}
			/* and fall thru */
		default:
		{
			/* Key header's algorithm --> OID */
			const CSSM_OID *oid = cssmAlgToOid(hdr.AlgorithmId);
			if(oid == NULL) {
				clErrorLog("CL SetField: Unknown key algorithm\n");
				CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
			}
			CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssKeyInfo.algorithm;
			coder.allocCopyItem(*oid, algId.algorithm);

			/* NULL algorithm parameters, always in this case */
			CL_nullAlgParams(algId);
			
			/* Copy key bits, destination is a BIT STRING */
			coder.allocCopyItem(cssmKey.KeyData, nssKeyInfo.subjectPublicKey);
			nssKeyInfo.subjectPublicKey.Length *= 8;
			break;
		}	
		case CSSM_ALGID_DSA:
		case CSSM_ALGID_ECDSA:
			if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_X509) {
				clErrorLog("CL SetField: DSA/ECDSA key must be in X509 format\n");
				CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
			}
			
			/* 
			 * All we do is decode the whole key blob into the 
			 * SubjectPublicKeyInfo.
			 */
			if(coder.decodeItem(cssmKey.KeyData, 
					kSecAsn1SubjectPublicKeyInfoTemplate, 
					&nssKeyInfo)) {
				clErrorLog("CL SetField: Error decoding DSA public key\n");
				CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
			}
			break;
	}
}
示例#3
0
void CL_cssmQualCertStatementsToNss(
	const CE_QC_Statements	 	&cdsaObj,
	NSS_QC_Statements 			&nssObj,
	SecNssCoder 				&coder) 
{
	memset(&nssObj, 0, sizeof(nssObj));
	uint32 numQcs = cdsaObj.numQCStatements;
	nssObj.qcStatements = 
		(NSS_QC_Statement **)clNssNullArray(numQcs, coder);
	for(uint32 dex=0; dex<numQcs; dex++) {
		nssObj.qcStatements[dex] = (NSS_QC_Statement *)
			coder.malloc(sizeof(NSS_QC_Statement));
		NSS_QC_Statement *dst = nssObj.qcStatements[dex];
		CE_QC_Statement *src = &cdsaObj.qcStatements[dex];
		memset(dst, 0, sizeof(*dst));
		coder.allocCopyItem(src->statementId, dst->statementId);
		if(src->semanticsInfo) {
			if(src->otherInfo) {
				/* this is either/or, not both */
				CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
			}

			/* encode this CE_SemanticsInformation */
			CE_SemanticsInformation *srcSI = src->semanticsInfo;
			NSS_SemanticsInformation dstSI;
			memset(&dstSI, 0, sizeof(dstSI));
			if(srcSI->semanticsIdentifier) {
				dstSI.semanticsIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA));
				coder.allocCopyItem(*srcSI->semanticsIdentifier, 
					*dstSI.semanticsIdentifier);
			}
			if(srcSI->nameRegistrationAuthorities) {
				dstSI.nameRegistrationAuthorities = 
					(NSS_GeneralNames *)coder.malloc(sizeof(NSS_GeneralNames));
				CL_cssmGeneralNamesToNss(*srcSI->nameRegistrationAuthorities,
					*dstSI.nameRegistrationAuthorities, coder);
			}
			PRErrorCode prtn = coder.encodeItem(&dstSI, kSecAsn1SemanticsInformationTemplate, 
				dst->info);
			if(prtn) {
				clErrorLog("CL_cssmQualCertStatementsToNss: encode error\n");
				CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
			}
			
		}
		if(src->otherInfo) {
			/* drop in as ASN_ANY */
			coder.allocCopyItem(*src->otherInfo, dst->info);
		}
	}
}
/* 
 * CSSM_X509_TYPE_VALUE_PAIR --> NSS_ATV 
 */
void CL_cssmAtvToNss(
	const CSSM_X509_TYPE_VALUE_PAIR	&cssmObj,
	NSS_ATV							&nssObj,
	SecNssCoder						&coder)
{
	memset(&nssObj, 0, sizeof(nssObj));
	
	/* copy the OID */
	coder.allocCopyItem(cssmObj.type, nssObj.type);
	
	/* tag and value */
	nssObj.value.tag = cssmObj.valueType;
	coder.allocCopyItem(cssmObj.value, nssObj.value.item);
}
示例#5
0
void CL_cssmInfoAccessToNss(
	const CE_AuthorityInfoAccess	&cdsaObj,
	NSS_AuthorityInfoAccess			&nssObj,
	SecNssCoder						&coder)  
{
	memset(&nssObj, 0, sizeof(nssObj));
	uint32 numDescs = cdsaObj.numAccessDescriptions;
	nssObj.accessDescriptions = (NSS_AccessDescription **)clNssNullArray(numDescs, coder);
	
	for(unsigned dex=0; dex<numDescs; dex++) {
		nssObj.accessDescriptions[dex] = coder.mallocn<NSS_AccessDescription>();
		CE_AccessDescription *src = &cdsaObj.accessDescriptions[dex];
		NSS_AccessDescription *dst = nssObj.accessDescriptions[dex];
		coder.allocCopyItem(src->accessMethod, dst->accessMethod);
		
		/* Convert general name, then encode it into destination */
		NSS_GeneralName nssGenName;
		CL_cssmGeneralNameToNss(src->accessLocation, nssGenName, coder);
		PRErrorCode prtn = coder.encodeItem(&nssGenName, kSecAsn1GeneralNameTemplate, 
			dst->encodedAccessLocation);
		if(prtn) {
			clErrorLog("CL_cssmInfoAccessToNss: encode error\n");
			CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
		}
	}
}
void p12CfDataToCssm(
	CFDataRef cf,
	CSSM_DATA &c,
	SecNssCoder &coder)
{
	coder.allocCopyItem(CFDataGetBytePtr(cf),
		CFDataGetLength(cf), c);
}
示例#7
0
/* 
 * CSSM time to NSS time. 
 */
void CL_cssmTimeToNss(
	const CSSM_X509_TIME &cssmTime, 
	NSS_TaggedItem &nssTime, 
	SecNssCoder &coder)
{
	nssTime.tag = cssmTime.timeType;
	coder.allocCopyItem(cssmTime.time, nssTime.item);
}
示例#8
0
void CL_cssmAuthorityKeyIdToNss(
	const CE_AuthorityKeyID 	&cdsaObj,
	NSS_AuthorityKeyId 			&nssObj,
	SecNssCoder 				&coder) 
{
	memset(&nssObj, 0, sizeof(nssObj));
	if(cdsaObj.keyIdentifierPresent) {
		nssObj.keyIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA));
		coder.allocCopyItem(cdsaObj.keyIdentifier, *nssObj.keyIdentifier);
	}
	if(cdsaObj.generalNamesPresent ) {
		/* GeneralNames, the hard one */
		CL_cssmGeneralNamesToNss(*cdsaObj.generalNames,
			nssObj.genNames, coder);
	}
	if(cdsaObj.serialNumberPresent) {
		coder.allocCopyItem(cdsaObj.serialNumber,nssObj.serialNumber);
	}
}
/*
 * Find private key by label, modify its Label attr to be the
 * hash of the associated public key. 
 * Also optionally re-sets the key's PrintName attribute; used to reset
 * this attr from the random label we create when first unwrap it 
 * to the friendly name we find later after parsing attributes.
 * Detection of a duplicate key when updating the key's attributes
 * results in a lookup of the original key and returning it in
 * foundKey.
 */
CSSM_RETURN p12SetPubKeyHash(
	CSSM_CSP_HANDLE 	cspHand,		// where the key lives
	CSSM_DL_DB_HANDLE 	dlDbHand,		// ditto
	CSSM_DATA			&keyLabel,		// for DB lookup
	CSSM_DATA_PTR		newPrintName,	// optional
	SecNssCoder			&coder,			// for mallocing newLabel
	CSSM_DATA			&newLabel,		// RETURNED with label as hash
	CSSM_KEY_PTR		&foundKey)		// RETURNED
{
	CSSM_QUERY						query;
	CSSM_SELECTION_PREDICATE		predicate;
	CSSM_DB_UNIQUE_RECORD_PTR		record = NULL;
	CSSM_RETURN						crtn;
	CSSM_HANDLE						resultHand = 0;
	CSSM_DATA						keyData = {0, NULL};
	CSSM_CC_HANDLE					ccHand = 0;
	CSSM_KEY_PTR					privKey = NULL;
	CSSM_DATA_PTR					keyDigest = NULL;
	
	assert(cspHand != 0);
	query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY;
	query.Conjunctive = CSSM_DB_NONE;
	query.NumSelectionPredicates = 1;
	predicate.DbOperator = CSSM_DB_EQUAL;
	
	predicate.Attribute.Info.AttributeNameFormat = 
		CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
	predicate.Attribute.Info.Label.AttributeName = 
		(char*) P12_KEY_ATTR_LABEL_AND_HASH;
	predicate.Attribute.Info.AttributeFormat = 
		CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
	/* hope this cast is OK */
	predicate.Attribute.Value = &keyLabel;
	query.SelectionPredicate = &predicate;
	
	query.QueryLimits.TimeLimit = 0;	// FIXME - meaningful?
	query.QueryLimits.SizeLimit = 1;	// FIXME - meaningful?
	query.QueryFlags = CSSM_QUERY_RETURN_DATA;	

	/* build Record attribute with one or two attrs */
	CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs;
	CSSM_DB_ATTRIBUTE_DATA attr[2];
	attr[0].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
	attr[0].Info.Label.AttributeName = (char*) P12_KEY_ATTR_LABEL_AND_HASH;
	attr[0].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
	if(newPrintName) {
		attr[1].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
		attr[1].Info.Label.AttributeName = (char*) P12_KEY_ATTR_PRINT_NAME;
		attr[1].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
	}
	recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY;
	recordAttrs.NumberOfAttributes = newPrintName ? 2 : 1;
	recordAttrs.AttributeData = attr;
	
	crtn = CSSM_DL_DataGetFirst(dlDbHand,
		&query,
		&resultHand,
		&recordAttrs,
		&keyData,			// theData
		&record);
	/* abort only on success */
	if(crtn != CSSM_OK) {
		p12LogCssmError("CSSM_DL_DataGetFirst", crtn);
		p12ErrorLog("***p12SetPubKeyHash: can't find private key\n");
		return crtn;
	}
	/* subsequent errors to errOut: */
	if(keyData.Data == NULL) {
		p12ErrorLog("***p12SetPubKeyHash: private key lookup failure\n");
		crtn = CSSMERR_CSSM_INTERNAL_ERROR;
		goto errOut;
	}
	privKey = (CSSM_KEY_PTR)keyData.Data;
	
	/* public key hash via passthrough - works on any key, any CSP/CSPDL.... */
	/*
	 * Warning! This relies on the current default ACL meaning "allow this
	 * current app to access this private key" since we created the key. 
	 */
	crtn = CSSM_CSP_CreatePassThroughContext(cspHand, privKey, &ccHand);
	if(crtn) {
		p12LogCssmError("CSSM_CSP_CreatePassThroughContext", crtn);
		goto errOut;
	}
	crtn = CSSM_CSP_PassThrough(ccHand,
		CSSM_APPLECSP_KEYDIGEST,
		NULL,
		(void **)&keyDigest);
	if(crtn) {
		p12LogCssmError("CSSM_CSP_PassThrough", crtn);
		goto errOut;
	}

	/* 
	 * Replace Label attr data with hash.
	 * NOTE: the module which allocated this attribute data - a DL -
	 * was loaded and attached by out client layer, not by us. Thus 
	 * we can't use the memory allocator functions *we* used when 
	 * attaching to the CSP - we have to use the ones
	 * which the client registered with the DL.
	 */
	freeCssmMemory(dlDbHand.DLHandle, attr[0].Value->Data);
	freeCssmMemory(dlDbHand.DLHandle, attr[0].Value);
	if(newPrintName) {
		freeCssmMemory(dlDbHand.DLHandle, attr[1].Value->Data);
		freeCssmMemory(dlDbHand.DLHandle, attr[1].Value);
	}
	/* modify key attributes */
	attr[0].Value = keyDigest;
	if(newPrintName) {
		attr[1].Value = newPrintName;
	}
	crtn = CSSM_DL_DataModify(dlDbHand,
			CSSM_DL_DB_RECORD_PRIVATE_KEY,
			record,
			&recordAttrs,
            NULL,				// DataToBeModified
			CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
	switch(crtn) {
		case CSSM_OK:
			/* give caller the key's new label */
			coder.allocCopyItem(*keyDigest, newLabel);
			break;
		default:
			p12LogCssmError("CSSM_DL_DataModify", crtn);
			break;
		case CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA:
		{
			/* 
			 * Special case: dup private key. The label we just tried to modify is 
			 * the public key hash so we can be confident that this really is a dup. 
			 * Delete it, look up the original, and return the original to caller. 
			 */ 
			CSSM_RETURN drtn = CSSM_DL_DataDelete(dlDbHand, record);
			if(drtn) {
				p12LogCssmError("CSSM_DL_DataDelete on dup key", drtn);
				crtn = drtn;
				break;
			}

			/* Free items created in last search */
			CSSM_DL_DataAbortQuery(dlDbHand, resultHand);
			resultHand = 0;
			CSSM_DL_FreeUniqueRecord(dlDbHand, record);
			record = NULL;
			
			/* lookup by label as public key hash this time */
			predicate.Attribute.Value = keyDigest;
			drtn = CSSM_DL_DataGetFirst(dlDbHand,
				&query,
				&resultHand,
				NULL,				// no attrs this time
				&keyData,		
				&record);
			if(drtn) {
				p12LogCssmError("CSSM_DL_DataGetFirst on original key", crtn);
				crtn = drtn;
				break;
			}
			foundKey = (CSSM_KEY_PTR)keyData.Data;
			/* give caller the key's actual label */
			coder.allocCopyItem(*keyDigest, newLabel);
			break;
		}
	}
	
errOut:
	/* free resources */
	if(resultHand) {
		CSSM_DL_DataAbortQuery(dlDbHand, resultHand);
	}
	if(record) {
		CSSM_DL_FreeUniqueRecord(dlDbHand, record);
	}
	if(ccHand) {
		CSSM_DeleteContext(ccHand);
	}
	if(privKey) {
		/* key created by the CSPDL */
		CSSM_FreeKey(cspHand, NULL, privKey, CSSM_FALSE);
		freeCssmMemory(dlDbHand.DLHandle, privKey);
	}
	if(keyDigest)  {
		/* mallocd by someone else's CSP */
		freeCssmMemory(cspHand, keyDigest->Data);
		freeCssmMemory(cspHand, keyDigest);
	}
	return crtn;
}
示例#10
0
/*
 * Wrap a private key, yielding shrouded key bits. 
 */
CSSM_RETURN p12WrapKey(
	CSSM_CSP_HANDLE		cspHand,
	CSSM_KEY_PTR		privKey,
	const CSSM_ACCESS_CREDENTIALS *privKeyCreds,
	CSSM_ALGORITHMS		keyAlg,				// of the unwrapping key
	CSSM_ALGORITHMS		encrAlg,
	CSSM_ALGORITHMS		pbeHashAlg,			// SHA1, MD5 only
	uint32				keySizeInBits,
	uint32				blockSizeInBytes,	// for IV
	CSSM_PADDING		padding,			// CSSM_PADDING_PKCS7, etc.
	CSSM_ENCRYPT_MODE	mode,				// CSSM_ALGMODE_CBCPadIV8, etc.
	uint32				iterCount,
	const CSSM_DATA		&salt,
	const CSSM_DATA		*pwd,		// unicode external representation
	const CSSM_KEY		*passKey,
	SecNssCoder			&coder,		// for mallocing keyBits
	CSSM_DATA			&shroudedKeyBits)	// RETURNED
{
	CSSM_RETURN crtn;
	CSSM_KEY ckey;
	CSSM_CC_HANDLE ccHand = 0;
	CSSM_KEY wrappedKey;
	CSSM_CONTEXT_ATTRIBUTE attr;
	CSSM_DATA descrData = {0, NULL};
	CSSM_ACCESS_CREDENTIALS creds;
	
	/* key must be extractable */
	if (!(privKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE)) {
		return errSecDataNotAvailable;
	}

	if(privKeyCreds == NULL) {
		/* i.e., key is from the bare CSP with no ACL support */
		memset(&creds, 0, sizeof(creds));
		privKeyCreds = &creds;
	}
	
	/* P12 style IV derivation, optional */
	CSSM_DATA iv = {0, NULL};
	CSSM_DATA_PTR ivPtr = NULL;
	if(blockSizeInBytes) {
		coder.allocItem(iv, blockSizeInBytes);
		ivPtr = &iv;
	}
	
	/* P12 style key derivation */
	crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
		keySizeInBits, iterCount, salt, pwd, passKey, iv);
	if(crtn) {
		return crtn;
	}	
	/* subsequent errors to errOut: */
		
	/* CSSM context */
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
		encrAlg,
		mode,
		NULL,			// access cred
		&ckey,
		ivPtr,			// InitVector, optional
		padding,	
		NULL,			// Params
		&ccHand);
	if(crtn) {
		p12LogCssmError("CSSM_CSP_CreateSymmetricContext", crtn);
		goto errOut;
	}
	
	memset(&wrappedKey, 0, sizeof(CSSM_KEY));
	
	/* specify PKCS8 wrap format */
	attr.AttributeType = CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT;
	attr.AttributeLength = sizeof(uint32);
	attr.Attribute.Uint32 = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
	crtn = CSSM_UpdateContextAttributes(
		ccHand,
		1,
		&attr);
	if(crtn) {
		p12LogCssmError("CSSM_UpdateContextAttributes", crtn);
		goto errOut;
	}
	
	crtn = CSSM_WrapKey(ccHand,
		privKeyCreds,
		privKey,
		&descrData,			// DescriptiveData
		&wrappedKey);
	if(crtn) {
		p12LogCssmError("CSSM_WrapKey", crtn);
	}
	else {
		coder.allocCopyItem(wrappedKey.KeyData, shroudedKeyBits);
		
		/* this was mallocd by CSP */
		freeCssmMemory(cspHand, wrappedKey.KeyData.Data);
	}
errOut:
	if(ccHand) {
		CSSM_DeleteContext(ccHand);
	}
	CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
	return crtn;
}
示例#11
0
/*
 * Decrypt (typically, an encrypted P7 ContentInfo contents)
 */
CSSM_RETURN p12Encrypt(
	CSSM_CSP_HANDLE		cspHand,
	const CSSM_DATA		&plainText,
	CSSM_ALGORITHMS		keyAlg,				
	CSSM_ALGORITHMS		encrAlg,
	CSSM_ALGORITHMS		pbeHashAlg,			// SHA1, MD5 only
	uint32				keySizeInBits,
	uint32				blockSizeInBytes,	// for IV
	CSSM_PADDING		padding,			// CSSM_PADDING_PKCS7, etc.
	CSSM_ENCRYPT_MODE	mode,				// CSSM_ALGMODE_CBCPadIV8, etc.
	uint32				iterCount,
	const CSSM_DATA		&salt,
	/* exactly one of the following two must be valid */
	const CSSM_DATA		*pwd,		// unicode external representation
	const CSSM_KEY		*passKey,
	SecNssCoder			&coder,		// for mallocing cipherText
	CSSM_DATA			&cipherText)
{
	CSSM_RETURN crtn;
	CSSM_KEY ckey;
	CSSM_CC_HANDLE ccHand = 0;
	CSSM_DATA ourCtext = {0, NULL};
	CSSM_DATA remData = {0, NULL};
	
	/* P12 style IV derivation, optional */
	CSSM_DATA iv = {0, NULL};
	CSSM_DATA_PTR ivPtr = NULL;
	if(blockSizeInBytes) {
		coder.allocItem(iv, blockSizeInBytes);
		ivPtr = &iv;
	}
	
	/* P12 style key derivation */
	crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
		keySizeInBits, iterCount, salt, pwd, passKey, iv);
	if(crtn) {
		return crtn;
	}	
	/* subsequent errors to errOut: */
		
	/* CSSM context */
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
		encrAlg,
		mode,
		NULL,			// access cred
		&ckey,
		ivPtr,			// InitVector, optional
		padding,	
		NULL,			// Params
		&ccHand);
	if(crtn) {
		cuPrintError("CSSM_CSP_CreateSymmetricContext", crtn);
		goto errOut;
	}
	
	/* go - CSP mallocs ctext and rem data */
	CSSM_SIZE bytesEncrypted;
	crtn = CSSM_EncryptData(ccHand,
		&plainText,
		1,
		&ourCtext,
		1,
		&bytesEncrypted,
		&remData);
	if(crtn) {
		cuPrintError("CSSM_DecryptData", crtn);
	}
	else {
		coder.allocCopyItem(ourCtext, cipherText);
		cipherText.Length = bytesEncrypted;
		
		/* plaintext copied into coder space; free the memory allocated
		 * by the CSP */
		freeCssmMemory(cspHand, ourCtext.Data);
	}
	/* an artifact of CSPFUllPLuginSession - this never contains
	 * valid data but sometimes gets mallocds */
	if(remData.Data) {
		freeCssmMemory(cspHand, remData.Data);
	}
errOut:
	if(ccHand) {
		CSSM_DeleteContext(ccHand);
	}
	CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
	return crtn;
}
void CL_cssmGeneralNameToNss(
	CE_GeneralName &cdsaObj,
	NSS_GeneralName &nssObj,		// actually an NSSTaggedItem
	SecNssCoder &coder)				// for temp decoding
{
	memset(&nssObj, 0, sizeof(nssObj));
	
	/*
	 * The default here is just to use the app-supplied data as is...
	 */
	nssObj.item = cdsaObj.name;
	unsigned char itemTag;			// for nssObj.tag
	bool doCopy = false;			// unless we have to modify tag byte
	unsigned char overrideTag;		// to force context-specific tag for
									//   an ASN_ANY
	PRErrorCode prtn;
									
	switch(cdsaObj.nameType) {
		case GNT_OtherName:	
			/*
			 * Caller supplies an CE_OtherName. Encode it.
			 */
			if((cdsaObj.name.Length != sizeof(CE_OtherName)) ||
			   (cdsaObj.name.Data == NULL)) {
				clErrorLog("CL_cssmGeneralNameToNss: OtherName.Length"
					" error\n");
				CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
			}
			prtn = coder.encodeItem(cdsaObj.name.Data,
				kSecAsn1OtherNameTemplate, nssObj.item);
			if(prtn) {
				clErrorLog("CL_cssmGeneralNameToNss: OtherName encode"
					" error\n");
				CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
			}
			itemTag = NGT_OtherName;
			break;
		case GNT_RFC822Name:		// IA5String
			itemTag = NGT_RFC822Name;
			break;
		case GNT_DNSName:			// IA5String
			itemTag = NGT_DNSName;
			break;
		case GNT_X400Address:		// caller's resposibility
			/*
			 * Encoded as ASN_ANY, the only thing we do is to 
			 * force the correct context-specific tag
			 */
			itemTag = GNT_X400Address;
			if(!cdsaObj.berEncoded) {
				clErrorLog("CL_cssmGeneralNameToNss: X400Address must"
					" be BER-encoded\n");
				CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
			}			
			overrideTag = SEC_ASN1_CONTEXT_SPECIFIC | 
				SEC_ASN1_CONSTRUCTED | NGT_X400Address;
			doCopy = true;
			break;
		case GNT_DirectoryName:	
		{
			/*
			 * Caller supplies an CSSM_X509_NAME. Convert to NSS
			 * format and encode it.
			 */
			if((cdsaObj.name.Length != sizeof(CSSM_X509_NAME)) || 
			   (cdsaObj.name.Data == NULL)) {
				clErrorLog("CL_cssmGeneralNameToNss: DirectoryName.Length"
					" error\n");
				CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
			}
			NSS_Name nssName;
			CSSM_X509_NAME_PTR cdsaName = 
				(CSSM_X509_NAME_PTR)cdsaObj.name.Data;
			CL_cssmNameToNss(*cdsaName, nssName, coder);
			prtn = coder.encodeItem(&nssName,
				kSecAsn1NameTemplate, nssObj.item);
			if(prtn) {
				clErrorLog("CL_cssmGeneralNameToNss: X509Name encode"
					" error\n");
				CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
			}
			itemTag = GNT_DirectoryName;
			
			/*
			 * AND, munge the tag to make it a context-specific
			 * sequence
			 * no, not needed, this is wrapped in an explicit...
			 */
			//nssObj.item.Data[0] = SEC_ASN1_CONTEXT_SPECIFIC | 
			//	SEC_ASN1_CONSTRUCTED | GNT_DirectoryName;

			break;
		}
		case GNT_EdiPartyName:		// caller's resposibility
			/*
			 * Encoded as ASN_ANY, the only thing we do is to 
			 * force the correct context-specific tag
			 */
			itemTag = GNT_EdiPartyName;
			if(!cdsaObj.berEncoded) {
				clErrorLog("CL_cssmGeneralNameToNss: EdiPartyName must"
					" be BER-encoded\n");
				CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
			}
			overrideTag = SEC_ASN1_CONTEXT_SPECIFIC |  NGT_X400Address;
			doCopy = true;
			break;
		case GNT_URI:				// IA5String
			itemTag = GNT_URI;
			break;
		case GNT_IPAddress:			// OCTET_STRING
			itemTag = NGT_IPAddress;
			break;
		case GNT_RegisteredID:		// OID
			itemTag = NGT_RegisteredID;
			break;
		default:
			clErrorLog("CL_cssmGeneralNameToNss: bad name tag\n");
			CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
	}
	if(doCopy) {
		coder.allocCopyItem(cdsaObj.name, nssObj.item);
		nssObj.item.Data[0] = overrideTag;
	}
	nssObj.tag = itemTag;
}