summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c')
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c667
1 files changed, 667 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c
new file mode 100644
index 000000000..e37439cf0
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c
@@ -0,0 +1,667 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_x500name.c
+ *
+ * X500Name Object Functions
+ *
+ */
+
+#include "pkix_pl_x500name.h"
+
+/* --Private-X500Name-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_X500Name_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_X500Name *name = NULL;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext),
+ PKIX_OBJECTNOTANX500NAME);
+
+ name = (PKIX_PL_X500Name *)object;
+
+ /* PORT_FreeArena will destroy arena, and, allocated on it, CERTName
+ * and SECItem */
+ if (name->arena) {
+ PORT_FreeArena(name->arena, PR_FALSE);
+ name->arena = NULL;
+ }
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_X500Name *name = NULL;
+ char *string = NULL;
+ PKIX_UInt32 strLength = 0;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext),
+ PKIX_OBJECTNOTANX500NAME);
+
+ name = (PKIX_PL_X500Name *)object;
+ string = CERT_NameToAscii(&name->nssDN);
+ if (!string){
+ PKIX_ERROR(PKIX_CERTNAMETOASCIIFAILED);
+ }
+ strLength = PL_strlen(string);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, string, strLength, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_X500Name *name = NULL;
+ SECItem *derBytes = NULL;
+ PKIX_UInt32 nameHash;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext),
+ PKIX_OBJECTNOTANX500NAME);
+
+ name = (PKIX_PL_X500Name *)object;
+
+ /* we hash over the bytes in the DER encoding */
+
+ derBytes = &name->derName;
+
+ PKIX_CHECK(pkix_hash
+ (derBytes->data, derBytes->len, &nameHash, plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = nameHash;
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_X500Name_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is an X500Name */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_X500NAME_TYPE, plContext),
+ PKIX_FIRSTOBJECTARGUMENTNOTANX500NAME);
+
+ /*
+ * Since we know firstObject is an X500Name, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't an X500Name, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_X500NAME_TYPE) goto cleanup;
+
+ PKIX_CHECK(
+ PKIX_PL_X500Name_Match((PKIX_PL_X500Name *)firstObject,
+ (PKIX_PL_X500Name *)secondObject,
+ pResult, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_X500NAME_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_X500Name_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_RegisterSelf");
+
+ entry.description = "X500Name";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_X500Name);
+ entry.destructor = pkix_pl_X500Name_Destroy;
+ entry.equalsFunction = pkix_pl_X500Name_Equals;
+ entry.hashcodeFunction = pkix_pl_X500Name_Hashcode;
+ entry.toStringFunction = pkix_pl_X500Name_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_X500NAME_TYPE] = entry;
+
+ PKIX_RETURN(X500NAME);
+}
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: pkix_pl_X500Name_CreateFromUtf8
+ *
+ * DESCRIPTION:
+ * Creates an X500Name object from the RFC1485 string representation pointed
+ * to by "stringRep", and stores the result at "pName". If the string cannot
+ * be successfully converted, a non-fatal error is returned.
+ *
+ * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed to be
+ * called only by pkix tests programs.
+ *
+ * PARAMETERS:
+ * "stringRep"
+ * Address of the RFC1485 string to be converted. Must be non-NULL.
+ * "pName"
+ * Address where the X500Name result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an X500NAME Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_CreateFromUtf8(
+ char *stringRep,
+ PKIX_PL_X500Name **pName,
+ void *plContext)
+{
+ PKIX_PL_X500Name *x500Name = NULL;
+ PLArenaPool *arena = NULL;
+ CERTName *nssDN = NULL;
+ SECItem *resultSecItem = NULL;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_CreateFromUtf8");
+ PKIX_NULLCHECK_TWO(pName, stringRep);
+
+ nssDN = CERT_AsciiToName(stringRep);
+ if (nssDN == NULL) {
+ PKIX_ERROR(PKIX_COULDNOTCREATENSSDN);
+ }
+
+ arena = nssDN->arena;
+
+ /* create a PKIX_PL_X500Name object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_X500NAME_TYPE,
+ sizeof (PKIX_PL_X500Name),
+ (PKIX_PL_Object **)&x500Name,
+ plContext),
+ PKIX_COULDNOTCREATEX500NAMEOBJECT);
+
+ /* populate the nssDN field */
+ x500Name->arena = arena;
+ x500Name->nssDN.arena = arena;
+ x500Name->nssDN.rdns = nssDN->rdns;
+
+ resultSecItem =
+ SEC_ASN1EncodeItem(arena, &x500Name->derName, nssDN,
+ CERT_NameTemplate);
+
+ if (resultSecItem == NULL){
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ *pName = x500Name;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ if (x500Name) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name,
+ plContext);
+ } else if (nssDN) {
+ CERT_DestroyName(nssDN);
+ }
+ }
+
+ PKIX_RETURN(X500NAME);
+}
+#endif /* BUILD_LIBPKIX_TESTS */
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetCERTName
+ *
+ * DESCRIPTION:
+ *
+ * Returns the pointer to CERTName member of X500Name structure.
+ *
+ * Returned pointed should not be freed.2
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose OrganizationName is to be extracted. Must be
+ * non-NULL.
+ * "pCERTName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetCERTName(
+ PKIX_PL_X500Name *xname,
+ CERTName **pCERTName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCERTName");
+ PKIX_NULLCHECK_TWO(xname, pCERTName);
+
+ *pCERTName = &xname->nssDN;
+
+ PKIX_RETURN(X500NAME);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_X500Name_CreateFromCERTName (see comments in pkix_pl_pki.h)
+ */
+
+PKIX_Error *
+PKIX_PL_X500Name_CreateFromCERTName(
+ SECItem *derName,
+ CERTName *name,
+ PKIX_PL_X500Name **pName,
+ void *plContext)
+{
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECFailure;
+ PKIX_PL_X500Name *x500Name = NULL;
+
+ PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_CreateFromCERTName");
+ PKIX_NULLCHECK_ONE(pName);
+ if (derName == NULL && name == NULL) {
+ PKIX_ERROR(PKIX_NULLARGUMENT);
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_X500NAME_TYPE,
+ sizeof (PKIX_PL_X500Name),
+ (PKIX_PL_Object **)&x500Name,
+ plContext),
+ PKIX_COULDNOTCREATEX500NAMEOBJECT);
+
+ x500Name->arena = arena;
+ x500Name->nssDN.arena = NULL;
+
+ if (derName != NULL) {
+ rv = SECITEM_CopyItem(arena, &x500Name->derName, derName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ }
+
+ if (name != NULL) {
+ rv = CERT_CopyName(arena, &x500Name->nssDN, name);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_CERTCOPYNAMEFAILED);
+ }
+ } else {
+ rv = SEC_QuickDERDecodeItem(arena, &x500Name->nssDN,
+ CERT_NameTemplate,
+ &x500Name->derName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_SECQUICKDERDECODERFAILED);
+ }
+ }
+
+ *pName = x500Name;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ if (x500Name) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name,
+ plContext);
+ } else if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+
+ PKIX_RETURN(X500NAME);
+}
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: PKIX_PL_X500Name_Create (see comments in pkix_pl_pki.h)
+ *
+ * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed
+ * to be called only by pkix tests programs.
+ */
+PKIX_Error *
+PKIX_PL_X500Name_Create(
+ PKIX_PL_String *stringRep,
+ PKIX_PL_X500Name **pName,
+ void *plContext)
+{
+ char *utf8String = NULL;
+ PKIX_UInt32 utf8Length = 0;
+
+ PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Create");
+ PKIX_NULLCHECK_TWO(pName, stringRep);
+
+ /*
+ * convert the input PKIX_PL_String to PKIX_UTF8_NULL_TERM.
+ * we need to use this format specifier because
+ * CERT_AsciiToName expects a NULL-terminated UTF8 string.
+ * Since UTF8 allow NUL characters in the middle of the
+ * string, this is buggy. However, as a workaround, using
+ * PKIX_UTF8_NULL_TERM gives us a NULL-terminated UTF8 string.
+ */
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stringRep,
+ PKIX_UTF8_NULL_TERM,
+ (void **)&utf8String,
+ &utf8Length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_CHECK(
+ pkix_pl_X500Name_CreateFromUtf8(utf8String,
+ pName, plContext),
+ PKIX_X500NAMECREATEFROMUTF8FAILED);
+
+cleanup:
+ PKIX_FREE(utf8String);
+
+ PKIX_RETURN(X500NAME);
+}
+#endif /* BUILD_LIBPKIX_TESTS */
+
+/*
+ * FUNCTION: PKIX_PL_X500Name_Match (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_X500Name_Match(
+ PKIX_PL_X500Name *firstX500Name,
+ PKIX_PL_X500Name *secondX500Name,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ SECItem *firstDerName = NULL;
+ SECItem *secondDerName = NULL;
+ SECComparison cmpResult;
+
+ PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Match");
+ PKIX_NULLCHECK_THREE(firstX500Name, secondX500Name, pResult);
+
+ if (firstX500Name == secondX500Name){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ firstDerName = &firstX500Name->derName;
+ secondDerName = &secondX500Name->derName;
+
+ PKIX_NULLCHECK_TWO(firstDerName->data, secondDerName->data);
+
+ cmpResult = SECITEM_CompareItem(firstDerName, secondDerName);
+ if (cmpResult != SECEqual) {
+ cmpResult = CERT_CompareName(&firstX500Name->nssDN,
+ &secondX500Name->nssDN);
+ }
+
+ *pResult = (cmpResult == SECEqual);
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetSECName
+ *
+ * DESCRIPTION:
+ * Returns a copy of CERTName DER representation allocated on passed in arena.
+ * If allocation on arena can not be done, NULL is stored at "pSECName".
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose CERTName flag is to be encoded. Must be
+ * non-NULL.
+ * "arena"
+ * Address of the PLArenaPool to be used in the encoding, and in which
+ * "pSECName" will be allocated. Must be non-NULL.
+ * "pSECName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetDERName(
+ PKIX_PL_X500Name *xname,
+ PLArenaPool *arena,
+ SECItem **pDERName,
+ void *plContext)
+{
+ SECItem *derName = NULL;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetDERName");
+
+ PKIX_NULLCHECK_THREE(xname, arena, pDERName);
+
+ /* Return NULL is X500Name was not created from DER */
+ if (xname->derName.data == NULL) {
+ *pDERName = NULL;
+ goto cleanup;
+ }
+
+ derName = SECITEM_ArenaDupItem(arena, &xname->derName);
+ if (derName == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ *pDERName = derName;
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetCommonName
+ *
+ * DESCRIPTION:
+ * Extracts the CommonName component of the X500Name object pointed to by
+ * "xname", and stores the result at "pCommonName". If the CommonName cannot
+ * be successfully extracted, NULL is stored at "pCommonName".
+ *
+ * The returned string must be freed with PORT_Free.
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose CommonName is to be extracted. Must be
+ * non-NULL.
+ * "pCommonName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetCommonName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCommonName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCommonName");
+ PKIX_NULLCHECK_TWO(xname, pCommonName);
+
+ *pCommonName = (unsigned char *)CERT_GetCommonName(&xname->nssDN);
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetCountryName
+ *
+ * DESCRIPTION:
+ * Extracts the CountryName component of the X500Name object pointed to by
+ * "xname", and stores the result at "pCountryName". If the CountryName cannot
+ * be successfully extracted, NULL is stored at "pCountryName".
+ *
+ * The returned string must be freed with PORT_Free.
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose CountryName is to be extracted. Must be
+ * non-NULL.
+ * "pCountryName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetCountryName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCountryName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCountryName");
+ PKIX_NULLCHECK_TWO(xname, pCountryName);
+
+ *pCountryName = (unsigned char*)CERT_GetCountryName(&xname->nssDN);
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetOrgName
+ *
+ * DESCRIPTION:
+ * Extracts the OrganizationName component of the X500Name object pointed to by
+ * "xname", and stores the result at "pOrgName". If the OrganizationName cannot
+ * be successfully extracted, NULL is stored at "pOrgName".
+ *
+ * The returned string must be freed with PORT_Free.
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose OrganizationName is to be extracted. Must be
+ * non-NULL.
+ * "pOrgName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetOrgName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pOrgName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetOrgName");
+ PKIX_NULLCHECK_TWO(xname, pOrgName);
+
+ *pOrgName = (unsigned char*)CERT_GetOrgName(&xname->nssDN);
+
+ PKIX_RETURN(X500NAME);
+}