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); } }
/* * 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; } }
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); }
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); }
/* * 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); }
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; }
/* * 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; }
/* * 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; }