/*
 * Build up a CSSM_X509_NAME from an arbitrary list of name/OID pairs. 
 * We do one a/v pair per RDN. 
 */
CSSM_X509_NAME * AppleTPSession::buildX509Name(
	const CSSM_APPLE_TP_NAME_OID *nameArray,
	unsigned numNames)
{
	CSSM_X509_NAME *top = (CSSM_X509_NAME *)malloc(sizeof(CSSM_X509_NAME));
	top->numberOfRDNs = numNames;
	if(numNames == 0) {
		/* legal! */
		top->RelativeDistinguishedName = NULL;
		return top;
	}
	top->RelativeDistinguishedName = 
		(CSSM_X509_RDN_PTR)malloc(sizeof(CSSM_X509_RDN) * numNames);
	CSSM_X509_RDN_PTR rdn;
	const CSSM_APPLE_TP_NAME_OID *nameOid;
	unsigned nameDex;
	for(nameDex=0; nameDex<numNames; nameDex++) {
		rdn = &top->RelativeDistinguishedName[nameDex];
		nameOid = &nameArray[nameDex];
		rdn->numberOfPairs = 1;
		rdn->AttributeTypeAndValue = (CSSM_X509_TYPE_VALUE_PAIR_PTR)
			malloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR));
		CSSM_X509_TYPE_VALUE_PAIR_PTR atvp = rdn->AttributeTypeAndValue;
		tpCopyCssmData(*this, nameOid->oid, &atvp->type);
		atvp->value.Length = strlen(nameOid->string);
		if(tpCompareOids(&CSSMOID_CountryName, nameOid->oid)) {
			/* 
			 * Country handled differently per RFC 3280 - must be printable,
			 * max of two characters in length
			 */
			if(atvp->value.Length > 2) {
				CssmError::throwMe(CSSMERR_TP_INVALID_DATA);
			}
			for(unsigned dex=0; dex<atvp->value.Length; dex++) {
				int c = nameOid->string[dex];
				if(!isprint(c) || (c == EOF)) {
					CssmError::throwMe(CSSMERR_TP_INVALID_DATA);
				}
			}
			atvp->valueType = BER_TAG_PRINTABLE_STRING;
		}
		/* other special cases per RFC 3280 */
		else if(tpCompareOids(&CSSMOID_DNQualifier, nameOid->oid)) {
			atvp->valueType = BER_TAG_PRINTABLE_STRING;
		}
		else if(tpCompareOids(&CSSMOID_SerialNumber, nameOid->oid)) {
			atvp->valueType = BER_TAG_PRINTABLE_STRING;
		}
		else if(tpCompareOids(&CSSMOID_EmailAddress, nameOid->oid)) {
			atvp->valueType = BER_TAG_IA5_STRING;
		}
		else {
			/* Default type */
			atvp->valueType = BER_TAG_PKIX_UTF8_STRING;
		}
		atvp->value.Data = (uint8 *)malloc(atvp->value.Length);
		memmove(atvp->value.Data, nameOid->string, atvp->value.Length);
	}
	return top;
}
/*
 * Malloc a CSSM_DATA, copy another one to it.
 */
CSSM_DATA_PTR tpMallocCopyCssmData(
	Allocator		&alloc,
	const CSSM_DATA	*src)
{
	CSSM_DATA_PTR dst = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA));
	tpCopyCssmData(alloc, src, dst);
	return dst;
}