Пример #1
0
/*
 * FUNCTION: pkix_pl_PrimHashTable_Destroy
 *
 *  Destroys PrimHashTable pointed to by "ht".
 *
 * PARAMETERS:
 *  "ht"
 *      Address of PrimHashtable to free. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Not Thread Safe - assumes exclusive access to "ht"
 *  (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS
 *  Returns NULL if the function succeeds.
 *  Returns a HashTable 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_PrimHashTable_Destroy(
        pkix_pl_PrimHashTable *ht,
        void *plContext)
{
        pkix_pl_HT_Elem *element = NULL;
        pkix_pl_HT_Elem *temp = NULL;
        PKIX_UInt32 i;

        PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Destroy");
        PKIX_NULLCHECK_ONE(ht);

        /* Free each element (list) */
        for (i = 0; i < ht->size; i++) {
                for (element = ht->buckets[i];
                    element != NULL;
                    element = temp) {
                        temp = element->next;
                        element->value = NULL;
                        element->key = NULL;
                        element->hashCode = 0;
                        element->next = NULL;
                        PKIX_FREE(element);
                }
        }

        /* Free the pointer to the list array */
        PKIX_FREE(ht->buckets);
        ht->size = 0;

        /* Free the table itself */
        PKIX_FREE(ht);

        PKIX_RETURN(HASHTABLE);
}
Пример #2
0
/*
 * FUNCTION: pkix_pl_Date_ToString
 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
 */
static PKIX_Error *
pkix_pl_Date_ToString(
        PKIX_PL_Object *object,
        PKIX_PL_String **pString,
        void *plContext)
{
        PKIX_PL_String *dateString = NULL;
        PKIX_PL_Date *date = NULL;
        SECItem *nssTime = NULL;
        char *asciiDate = NULL;

        PKIX_ENTER(DATE, "pkix_pl_Date_toString");
        PKIX_NULLCHECK_TWO(object, pString);

        PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
                    PKIX_OBJECTNOTDATE);

        date = (PKIX_PL_Date *)object;

        nssTime = &date->nssTime;

        PKIX_CHECK(pkix_pl_Date_ToString_Helper
                    (nssTime, &dateString, plContext),
                    PKIX_DATETOSTRINGHELPERFAILED);

        *pString = dateString;

cleanup:

        PKIX_FREE(asciiDate);

        PKIX_RETURN(DATE);
}
Пример #3
0
/*
 * FUNCTION: PKIX_PL_ByteArray_GetPointer (see comments in pkix_pl_system.h)
 */
PKIX_Error *
PKIX_PL_ByteArray_GetPointer(
        PKIX_PL_ByteArray *byteArray,
        void **pArray,
        void *plContext)
{
        void *bytes = NULL;
        PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_GetPointer");
        PKIX_NULLCHECK_TWO(byteArray, pArray);

        if (byteArray->length != 0){
                PKIX_CHECK(PKIX_PL_Malloc
                            (byteArray->length, &bytes, plContext),
                            PKIX_MALLOCFAILED);

                PKIX_BYTEARRAY_DEBUG("\tCalling PORT_Memcpy).\n");
                (void) PORT_Memcpy
                        (bytes, byteArray->array, byteArray->length);
        }

        *pArray = bytes;

cleanup:

        if (PKIX_ERROR_RECEIVED){
                PKIX_FREE(bytes);
        }

        PKIX_RETURN(BYTEARRAY);
}
Пример #4
0
/*
 * FUNCTION: pkix_pl_PrimHashTable_RemoveFIFO
 * DESCRIPTION:
 *
 *  Remove the first entry in the bucket the "hashCode" is designated in
 *  the hashtable "ht". Since new entry is added at end of the link list
 *  the first one is the oldest (FI) therefore removed first (FO).
 *
 * PARAMETERS:
 *  "ht"
 *      Address of PrimHashtable to get entries count. Must be non-NULL.
 *  "hashCode"
 *      Hashcode value of the key.
 *  "pKey"
 *      Address of key of the entry deleted. Must be non-NULL.
 *  "pValue"
 *      Address of Value of the entry deleted. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Not Thread Safe - assumes exclusive access to "ht"
 *  (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a HashTable 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_PrimHashTable_RemoveFIFO(
        pkix_pl_PrimHashTable *ht,
        PKIX_UInt32 hashCode,
        void **pKey,
        void **pValue,
        void *plContext)
{
        pkix_pl_HT_Elem *element = NULL;

        PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove");
        PKIX_NULLCHECK_THREE(ht, pKey, pValue);

        element = (ht->buckets)[hashCode%ht->size];

        if (element != NULL) {

                *pKey = element->key;
                *pValue = element->value;
                ht->buckets[hashCode%ht->size] = element->next;
                element->key = NULL;
                element->value = NULL;
                element->next = NULL;
                PKIX_FREE(element);
        }

        PKIX_RETURN(HASHTABLE);
}
Пример #5
0
/*
 * FUNCTION: pkix_pl_CRL_GetSignatureAlgId
 *
 * DESCRIPTION:
 *  Retrieves a pointer to the OID that represents the signature algorithm of
 *  the CRL pointed to by "crl" and stores it at "pSignatureAlgId".
 *
 *  AlgorithmIdentifier  ::=  SEQUENCE  {
 *      algorithm               OBJECT IDENTIFIER,
 *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
 *
 * PARAMETERS:
 *  "crl"
 *      Address of CRL whose signature algorithm OID is to be stored.
 *      Must be non-NULL.
 *  "pSignatureAlgId"
 *      Address where object pointer 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 CRL Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */
static PKIX_Error *
pkix_pl_CRL_GetSignatureAlgId(
    PKIX_PL_CRL *crl,
    PKIX_PL_OID **pSignatureAlgId,
    void *plContext)
{
    CERTCrl *nssCrl = NULL;
    PKIX_PL_OID *signatureAlgId = NULL;
    SECAlgorithmID algorithm;
    SECItem algBytes;
    char *asciiOID = NULL;

    PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId");
    PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId);

    /* if we don't have a cached copy from before, we create one */
    if (crl->signatureAlgId == NULL) {

        PKIX_OBJECT_LOCK(crl);

        if (crl->signatureAlgId == NULL) {

            nssCrl = &(crl->nssSignedCrl->crl);
            algorithm = nssCrl->signatureAlg;
            algBytes = algorithm.algorithm;

            PKIX_NULLCHECK_ONE(algBytes.data);
            if (algBytes.len == 0) {
                PKIX_ERROR_FATAL(PKIX_OIDBYTESLENGTH0);
            }

            PKIX_CHECK(pkix_pl_oidBytes2Ascii
                       (&algBytes, &asciiOID, plContext),
                       PKIX_OIDBYTES2ASCIIFAILED);

            PKIX_CHECK(PKIX_PL_OID_Create
                       (asciiOID, &signatureAlgId, plContext),
                       PKIX_OIDCREATEFAILED);

            /* save a cached copy in case it is asked for again */
            crl->signatureAlgId = signatureAlgId;
        }

        PKIX_OBJECT_UNLOCK(crl);

    }

    PKIX_INCREF(crl->signatureAlgId);
    *pSignatureAlgId = crl->signatureAlgId;

cleanup:

    PKIX_FREE(asciiOID);

    PKIX_RETURN(CRL);
}
/*
 * FUNCTION: pkix_pl_OtherName_Create
 * DESCRIPTION:
 *
 *  Creates new OtherName which represents the CERTGeneralName pointed to by
 *  "nssAltName" and stores it at "pOtherName".
 *
 * PARAMETERS:
 *  "nssAltName"
 *      Address of CERTGeneralName. Must be non-NULL.
 *  "pOtherName"
 *      Address where object pointer 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 GeneralName Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */
static PKIX_Error *
pkix_pl_OtherName_Create(
        CERTGeneralName *nssAltName,
        OtherName **pOtherName,
        void *plContext)
{
        OtherName *otherName = NULL;
        SECItem secItemName;
        SECItem secItemOID;
        SECStatus rv;

        PKIX_ENTER(GENERALNAME, "pkix_pl_OtherName_Create");
        PKIX_NULLCHECK_TWO(nssAltName, pOtherName);

        PKIX_CHECK(PKIX_PL_Malloc
                    (sizeof (OtherName), (void **)&otherName, plContext),
                    PKIX_MALLOCFAILED);

        /* make a copy of the name field */
        PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
        rv = SECITEM_CopyItem
                (NULL, &otherName->name, &nssAltName->name.OthName.name);
        if (rv != SECSuccess) {
                PKIX_ERROR(PKIX_OUTOFMEMORY);
        }

        /* make a copy of the oid field */
        PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
        rv = SECITEM_CopyItem
                (NULL, &otherName->oid, &nssAltName->name.OthName.oid);
        if (rv != SECSuccess) {
                PKIX_ERROR(PKIX_OUTOFMEMORY);
        }

        *pOtherName = otherName;

cleanup:

        if (otherName && PKIX_ERROR_RECEIVED){
                secItemName = otherName->name;
                secItemOID = otherName->oid;

                PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
                SECITEM_FreeItem(&secItemName, PR_FALSE);

                PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
                SECITEM_FreeItem(&secItemOID, PR_FALSE);

                PKIX_FREE(otherName);
                otherName = NULL;
        }

        PKIX_RETURN(GENERALNAME);
}
Пример #7
0
/*
 * FUNCTION: PKIX_PL_Date_Create_UTCTime (see comments in pkix_pl_pki.h)
 */
PKIX_Error *
PKIX_PL_Date_Create_UTCTime(
        PKIX_PL_String *stringRep,
        PKIX_PL_Date **pDate,
        void *plContext)
{
        PKIX_PL_Date *date = NULL;
        char *asciiString = NULL;
        PKIX_UInt32 escAsciiLength;
        SECStatus rv;
        PRTime time;

        PKIX_ENTER(DATE, "PKIX_PL_Date_Create_UTCTime");
        PKIX_NULLCHECK_ONE(pDate);

        if (stringRep == NULL){
                PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n");
                time = PR_Now();
        } else {
                /* convert the input PKIX_PL_String to PKIX_ESCASCII */
                PKIX_CHECK(PKIX_PL_String_GetEncoded
                            (stringRep,
                            PKIX_ESCASCII,
                            (void **)&asciiString,
                            &escAsciiLength,
                            plContext),
                            PKIX_STRINGGETENCODEDFAILED);

                PKIX_DATE_DEBUG("\t\tCalling DER_AsciiToTime).\n");
                /* DER_AsciiToTime only supports UTCTime (2-digit years) */
                rv = DER_AsciiToTime(&time, asciiString);
                if (rv != SECSuccess){
                        PKIX_ERROR(PKIX_DERASCIITOTIMEFAILED);
                }
        }

        /* create a PKIX_PL_Date object */
        PKIX_CHECK(PKIX_PL_Object_Alloc
                    (PKIX_DATE_TYPE,
                    sizeof (PKIX_PL_Date),
                    (PKIX_PL_Object **)&date,
                    plContext),
                    PKIX_COULDNOTCREATEOBJECT);

        /* populate the nssTime field */
        date->nssTime = time;
        *pDate = date;

cleanup:
        PKIX_FREE(asciiString);

        PKIX_RETURN(DATE);
}
/*
 * FUNCTION: pkix_pl_GeneralName_Destroy
 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
 */
static PKIX_Error *
pkix_pl_GeneralName_Destroy(
        PKIX_PL_Object *object,
        void *plContext)
{
        PKIX_PL_GeneralName *name = NULL;
        SECItem secItemName;
        SECItem secItemOID;

        PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Destroy");
        PKIX_NULLCHECK_ONE(object);

        PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
                    PKIX_OBJECTNOTGENERALNAME);

        name = (PKIX_PL_GeneralName *)object;

        PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
        SECITEM_FreeItem(name->other, PR_TRUE);
        name->other = NULL;

        if (name->OthName){
                secItemName = name->OthName->name;
                secItemOID = name->OthName->oid;

                PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
                SECITEM_FreeItem(&secItemName, PR_FALSE);

                PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
                SECITEM_FreeItem(&secItemOID, PR_FALSE);

                PKIX_FREE(name->OthName);
                name->OthName = NULL;
        }

        if (name->nssGeneralNameList != NULL) {
                PKIX_GENERALNAME_DEBUG
                        ("\t\tCalling CERT_DestroyGeneralNameList).\n");
                CERT_DestroyGeneralNameList(name->nssGeneralNameList);
        }

        PKIX_DECREF(name->directoryName);
        PKIX_DECREF(name->oid);

cleanup:

        PKIX_RETURN(GENERALNAME);
}
Пример #9
0
/*
 * FUNCTION: pkix_pl_ipAddrBytes2Ascii
 * DESCRIPTION:
 *
 *  Converts the DER encoding of an IPAddress pointed to by "secItem" to an
 *  ASCII representation and stores the result at "pAscii". The ASCII
 *  representation is guaranteed to end with a NUL character. The input
 *  SECItem must contain non-NULL data and must have a positive length.
 *
 *  The return value "pAscii" is not reference-counted and will need to
 *  be freed with PKIX_PL_Free.
 *  XXX this function assumes that IPv4 addresses are being used
 *  XXX what about IPv6? can NSS tell the difference
 *
 * PARAMETERS
 *  "secItem"
 *      Address of SECItem which contains bytes and length of DER encoding.
 *      Must be non-NULL.
 *  "pAscii"
 *      Address where object pointer 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 Object 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_ipAddrBytes2Ascii(
        SECItem *secItem,
        char **pAscii,
        void *plContext)
{
        char *data = NULL;
        PKIX_UInt32 *tokens = NULL;
        PKIX_UInt32 numTokens = 0;
        PKIX_UInt32 i = 0;
        char *asciiString = NULL;

        PKIX_ENTER(OBJECT, "pkix_pl_ipAddrBytes2Ascii");
        PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data);

        if (secItem->len == 0) {
                PKIX_ERROR_FATAL(PKIX_IPADDRBYTES2ASCIIDATALENGTHZERO);
        }

        data = (char *)(secItem->data);
        numTokens = secItem->len;

        /* allocate space for array of integers */
        PKIX_CHECK(PKIX_PL_Malloc
                    (numTokens * sizeof (PKIX_UInt32),
                    (void **)&tokens,
                    plContext),
                    PKIX_MALLOCFAILED);

        /* populate array of integers */
        for (i = 0; i < numTokens; i++){
                tokens[i] = data[i];
        }

        /* convert array of integers to ASCII */
        PKIX_CHECK(pkix_pl_helperBytes2Ascii
                    (tokens, numTokens, &asciiString, plContext),
                    PKIX_HELPERBYTES2ASCIIFAILED);

        *pAscii = asciiString;

cleanup:

        PKIX_FREE(tokens);

        PKIX_RETURN(OBJECT);
}
Пример #10
0
/*
 * FUNCTION: pkix_pl_PrimHashTable_Create
 * DESCRIPTION:
 *
 *  Creates a new PrimHashtable object with a number of buckets equal to
 *  "numBuckets" and stores the result at "pResult".
 *
 * PARAMETERS:
 *  "numBuckets"
 *      The number of hash table buckets. Must be non-zero.
 *  "pResult"
 *      Address where PrimHashTable pointer 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_PrimHashTable_Create(
        PKIX_UInt32 numBuckets,
        pkix_pl_PrimHashTable **pResult,
        void *plContext)
{
        pkix_pl_PrimHashTable *primHashTable = NULL;
        PKIX_UInt32 i;

        PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Create");
        PKIX_NULLCHECK_ONE(pResult);

        if (numBuckets == 0) {
                PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO);
        }

        /* Allocate a new hashtable */
        PKIX_CHECK(PKIX_PL_Malloc
                    (sizeof (pkix_pl_PrimHashTable),
                    (void **)&primHashTable,
                    plContext),
                    PKIX_MALLOCFAILED);

        primHashTable->size = numBuckets;

        /* Allocate space for the buckets */
        PKIX_CHECK(PKIX_PL_Malloc
                    (numBuckets * sizeof (pkix_pl_HT_Elem*),
                    (void **)&primHashTable->buckets,
                    plContext),
                    PKIX_MALLOCFAILED);

        for (i = 0; i < numBuckets; i++) {
                primHashTable->buckets[i] = NULL;
        }

        *pResult = primHashTable;

cleanup:

        if (PKIX_ERROR_RECEIVED){
                PKIX_FREE(primHashTable);
        }

        PKIX_RETURN(HASHTABLE);
}
Пример #11
0
/*
 * FUNCTION: pkix_Destroy_Object
 * DESCRIPTION:
 *
 *  Destroys and deallocates Object pointed to by "object". The caller is
 *  assumed to hold the Object's lock, which is acquired in
 *  PKIX_PL_Object_DecRef().
 *
 * PARAMETERS:
 *  "object"
 *      Address of Object to destroy. 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.
 */
static PKIX_Error *
pkix_pl_Object_Destroy(
        PKIX_PL_Object *object,
        void *plContext)
{
        PKIX_PL_Object *objectHeader = NULL;

        PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy");
        PKIX_NULLCHECK_ONE(object);

#ifdef PKIX_OBJECT_LEAK_TEST
        PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
#else
        PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
#endif /* PKIX_OBJECT_LEAK_TEST */

        /* Attempt to delete an object still being used */
        if (objectHeader->references != 0) {
                PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED);
        }

        PKIX_DECREF(objectHeader->stringRep);

        /* Destroy this object's lock */
        PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n");
        PR_DestroyLock(objectHeader->lock);
        objectHeader->lock = NULL;
        object = NULL;

        objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED;

#ifdef PKIX_OBJECT_LEAK_TEST
        memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSize);
#endif

        PKIX_FREE(objectHeader);

cleanup:
#ifdef PKIX_OBJECT_LEAK_TEST
fatal:
#endif

        PKIX_RETURN(OBJECT);
}
Пример #12
0
/*
 * FUNCTION: pkix_pl_ByteArray_Destroy
 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
 */
static PKIX_Error *
pkix_pl_ByteArray_Destroy(
        PKIX_PL_Object *object,
        void *plContext)
{
        PKIX_PL_ByteArray *array = NULL;

        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Destroy");
        PKIX_NULLCHECK_ONE(object);

        PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
                    PKIX_OBJECTNOTBYTEARRAY);

        array = (PKIX_PL_ByteArray*)object;

        PKIX_FREE(array->array);
        array->array = NULL;
        array->length = 0;

cleanup:

        PKIX_RETURN(BYTEARRAY);
}
Пример #13
0
/*
 * FUNCTION: pkix_pl_ByteArray_ToString
 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
 */
static PKIX_Error *
pkix_pl_ByteArray_ToString(
        PKIX_PL_Object *object,
        PKIX_PL_String **pString,
        void *plContext)
{
        PKIX_PL_ByteArray *array = NULL;
        char *tempText = NULL;
        char *stringText = NULL; /* "[OOO, OOO, ... OOO]" */
        PKIX_UInt32 i, outputLen, bufferSize;

        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToString");
        PKIX_NULLCHECK_TWO(object, pString);

        PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
                    PKIX_OBJECTNOTBYTEARRAY);

        array = (PKIX_PL_ByteArray *)object;

        if ((array->length) == 0) {
                PKIX_CHECK(PKIX_PL_String_Create
                        (PKIX_ESCASCII, "[]", 0, pString, plContext),
                        PKIX_COULDNOTCREATESTRING);
        } else {
                /* Allocate space for "XXX, ". */
                bufferSize = 2+5*array->length;

                /* Allocate space for format string */
                PKIX_CHECK(PKIX_PL_Malloc
                        (bufferSize, (void **)&stringText, plContext),
                        PKIX_MALLOCFAILED);

                stringText[0] = 0;
                outputLen = 0;

                PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
                tempText =
                        PR_smprintf
                            ("[%03u", (0x0FF&((char *)(array->array))[0]));
                PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
                outputLen += PL_strlen(tempText);

                PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
                stringText = PL_strcat(stringText, tempText);

                PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
                PR_smprintf_free(tempText);

                for (i = 1; i < array->length; i++) {
                        PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
                        tempText = PR_smprintf
                                (", %03u",
                                (0x0FF&((char *)(array->array))[i]));

                        if (tempText == NULL){
                                PKIX_ERROR(PKIX_PRSMPRINTFFAILED);
                        }

                        PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
                        outputLen += PL_strlen(tempText);

                        PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
                        stringText = PL_strcat(stringText, tempText);

                        PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
                        PR_smprintf_free(tempText);
                        tempText = NULL;
                }

                stringText[outputLen++] = ']';
                stringText[outputLen] = 0;

                PKIX_CHECK(PKIX_PL_String_Create
                        (PKIX_ESCASCII, stringText, 0, pString, plContext),
                        PKIX_STRINGCREATEFAILED);

        }

cleanup:

        PKIX_FREE(stringText);
        PKIX_RETURN(BYTEARRAY);
}
Пример #14
0
/*
 * FUNCTION: pkix_UTF16_to_EscASCII
 * DESCRIPTION:
 *
 *  Converts array of bytes pointed to by "utf16String" with length of
 *  "utf16Length" (which must be even) into a freshly allocated Escaped ASCII
 *  string and stores a pointer to that string at "pDest" and stores the
 *  string's length at "pLength". The Escaped ASCII string's length does not
 *  include the final NUL character. The caller is responsible for freeing
 *  "pDest" using PKIX_PL_Free. If "debug" is set, uses EscASCII_Debug
 *  encoding.
 *
 * PARAMETERS:
 *  "utf16String"
 *      Address of array of bytes representing data source. Must be non-NULL.
 *  "utf16Length"
 *      Length of data source. Must be even.
 *  "debug"
 *      Boolean value indicating whether debug mode is desired.
 *  "pDest"
 *      Address where data will be stored. Must be non-NULL.
 *  "pLength"
 *      Address where data length 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 String 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_UTF16_to_EscASCII(
        const void *utf16String,
        PKIX_UInt32 utf16Length,
        PKIX_Boolean debug,
        char **pDest,
        PKIX_UInt32 *pLength,
        void *plContext)
{
        char *destPtr = NULL;
        PKIX_UInt32 i, charLen;
        PKIX_UInt32 x = 0, y = 0, z = 0;
        unsigned char *utf16Char = (unsigned char *)utf16String;

        PKIX_ENTER(STRING, "pkix_UTF16_to_EscASCII");
        PKIX_NULLCHECK_THREE(utf16String, pDest, pLength);

        /* Assume every pair of bytes becomes &#xNNNN; */
        charLen = 4*utf16Length;

        /* utf16Lenght must be even */
        if ((utf16Length % 2) != 0){
                PKIX_ERROR(PKIX_UTF16ALIGNMENTERROR);
        }

        /* Count how many bytes we need */
        for (i = 0; i < utf16Length; i += 2) {
                if ((utf16Char[i] == 0x00)&&
                        pkix_isPlaintext(utf16Char[i+1], debug)) {
                        if (utf16Char[i+1] == '&') {
                                /* Need to convert this to &amp; */
                                charLen -= 3;
                        } else {
                                /* We can fit this into one char */
                                charLen -= 7;
                        }
                } else if ((utf16Char[i] >= 0xD8) && (utf16Char[i] <= 0xDB)) {
                        if ((i+3) >= utf16Length) {
                                PKIX_ERROR(PKIX_UTF16HIGHZONEALIGNMENTERROR);
                        } else if ((utf16Char[i+2] >= 0xDC)&&
                                (utf16Char[i+2] <= 0xDF)) {
                                /* Quartet of bytes will become &#xNNNNNNNN; */
                                charLen -= 4;
                                /* Quartet of bytes will produce 12 chars */
                                i += 2;
                        } else {
                                /* Second pair should be DC00-DFFF */
                                PKIX_ERROR(PKIX_UTF16LOWZONEERROR);
                        }
                }
        }

        *pLength = charLen;

        /* Ensure this string is null terminated */
        charLen++;

        /* Allocate space for character array */
        PKIX_CHECK(PKIX_PL_Malloc(charLen, (void **)pDest, plContext),
                    PKIX_MALLOCFAILED);

        destPtr = *pDest;
        for (i = 0; i < utf16Length; i += 2) {
                if ((utf16Char[i] == 0x00)&&
                    pkix_isPlaintext(utf16Char[i+1], debug)) {
                        /* Write a single character */
                        *destPtr++ = utf16Char[i+1];
                } else if ((utf16Char[i+1] == '&') && (utf16Char[i] == 0x00)){
                        *destPtr++ = '&';
                        *destPtr++ = 'a';
                        *destPtr++ = 'm';
                        *destPtr++ = 'p';
                        *destPtr++ = ';';
                } else if ((utf16Char[i] >= 0xD8)&&
                            (utf16Char[i] <= 0xDB)&&
                            (utf16Char[i+2] >= 0xDC)&&
                            (utf16Char[i+2] <= 0xDF)) {
                        /*
                         * Special UTF pairs are of the form:
                         * x = D800..DBFF; y = DC00..DFFF;
                         * The result is of the form:
                         * ((x - D800) * 400 + (y - DC00)) + 0001 0000
                         */
                        x = 0x0FFFF & ((utf16Char[i]<<8) | utf16Char[i+1]);
                        y = 0x0FFFF & ((utf16Char[i+2]<<8) | utf16Char[i+3]);
                        z = ((x - 0xD800) * 0x400 + (y - 0xDC00)) + 0x00010000;

                        /* Sprintf &#xNNNNNNNN; */
                        PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n");
                        if (PR_snprintf(destPtr, 13, "&#x%08X;", z) ==
                            (PKIX_UInt32)(-1)) {
                                PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
                        }
                        i += 2;
                        destPtr += 12;
                } else {
                        /* Sprintf &#xNNNN; */
                        PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n");
                        if (PR_snprintf
                            (destPtr,
                            9,
                            "&#x%02X%02X;",
                            utf16Char[i],
                            utf16Char[i+1]) ==
                            (PKIX_UInt32)(-1)) {
                                PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
                        }
                        destPtr += 8;
                }
        }
        *destPtr = '\0';

cleanup:

        if (PKIX_ERROR_RECEIVED){
                PKIX_FREE(*pDest);
        }

        PKIX_RETURN(STRING);
}
Пример #15
0
/*
 * FUNCTION: pkix_pl_PrimHashTable_Remove
 * DESCRIPTION:
 *
 *  Removes any objects with the key pointed to by "key" and hashCode value
 *  equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
 *  function pointed to by "keyComp" to compare keys, and stores the object's
 *  value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
 *  This function sets "pResult" to NULL if the key is not in the hashtable.
 *
 * PARAMETERS:
 *  "ht"
 *      Address of PrimHashtable to remove object. Must be non-NULL.
 *  "key"
 *      Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
 *      Must be non-NULL.
 *  "value"
 *      Address of Object to be added to PrimHashtable. Must be non-NULL.
 *  "hashCode"
 *      Hashcode value of the key.
 *  "keyComp"
 *      Address of function used to determine if two keys are equal.
 *      If NULL, pkix_pl_KeyComparator_Default is used.
 *  "pResult"
 *      Address where value will be stored. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Not Thread Safe - assumes exclusive access to "ht"
 *  (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a HashTable 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_PrimHashTable_Remove(
        pkix_pl_PrimHashTable *ht,
        void *key,
        PKIX_UInt32 hashCode,
        PKIX_PL_EqualsCallback keyComp,
        void **pKey,
        void **pValue,
        void *plContext)
{
        pkix_pl_HT_Elem *element = NULL;
        pkix_pl_HT_Elem *prior = NULL;
        PKIX_Boolean compResult;

        PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove");
        PKIX_NULLCHECK_FOUR(ht, key, pKey, pValue);

        *pKey = NULL;
        *pValue = NULL;

        for (element = ht->buckets[hashCode%ht->size], prior = element;
            (element != NULL);
            prior = element, element = element->next) {

                if (element->hashCode != hashCode){
                        /* no possibility of a match */
                        continue;
                }

                if (keyComp == NULL){
                        PKIX_CHECK(pkix_pl_KeyComparator_Default
                                ((PKIX_UInt32 *)key,
                                (PKIX_UInt32 *)(element->key),
                                &compResult,
                                plContext),
                                PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
                } else {
                        PKIX_CHECK(keyComp
                                ((PKIX_PL_Object *)key,
                                (PKIX_PL_Object *)(element->key),
                                &compResult,
                                plContext),
                                PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
                }

                if ((element->hashCode == hashCode) &&
                    (compResult == PKIX_TRUE)){
                        if (element != prior) {
                                prior->next = element->next;
                        } else {
                                ht->buckets[hashCode%ht->size] = element->next;
                        }
                        *pKey = element->key;
                        *pValue = element->value;
                        element->key = NULL;
                        element->value = NULL;
                        element->next = NULL;
                        PKIX_FREE(element);
                        goto cleanup;
                }
        }

cleanup:

        PKIX_RETURN(HASHTABLE);
}
Пример #16
0
/*
 * FUNCTION: pkix_pl_ByteArray_ToHexString
 * DESCRIPTION:
 *
 *  Creates a hex-String representation of the ByteArray pointed to by "array"
 *  and stores the result at "pString". The hex-String consists of hex-digit
 *  pairs separated by spaces, and the entire string enclosed within square
 *  brackets, e.g. [43 61 6E 20 79 6F 75 20 72 65 61 64 20 74 68 69 73 3F].
 *  A zero-length ByteArray is represented as [].
 * PARAMETERS
 *  "array"
 *      ByteArray to be represented by the hex-String; must be non-NULL
 *  "pString"
 *      Address where String 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 Cert 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_ByteArray_ToHexString(
        PKIX_PL_ByteArray *array,
        PKIX_PL_String **pString,
        void *plContext)
{
        char *tempText = NULL;
        char *stringText = NULL; /* "[XX XX XX ...]" */
        PKIX_UInt32 i, outputLen, bufferSize;

        PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToHexString");
        PKIX_NULLCHECK_TWO(array, pString);

        if ((array->length) == 0) {
                PKIX_CHECK(PKIX_PL_String_Create
                        (PKIX_ESCASCII, "[]", 0, pString, plContext),
                        PKIX_COULDNOTCREATESTRING);
        } else {
                /*
                 * Allocate space for format string
                 * '[' + "XX" + (n-1)*" XX" + ']' + '\0'
                 */
                bufferSize = 2 + (3*(array->length));

                PKIX_CHECK(PKIX_PL_Malloc
                        (bufferSize, (void **)&stringText, plContext),
                        PKIX_COULDNOTALLOCATEMEMORY);

                stringText[0] = 0;
                outputLen = 0;

                PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
                tempText = PR_smprintf
                        ("[%02X", (0x0FF&((char *)(array->array))[0]));
                PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
                outputLen += PL_strlen(tempText);

                PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
                stringText = PL_strcat(stringText, tempText);

                PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
                PR_smprintf_free(tempText);

                for (i = 1; i < array->length; i++) {
                        PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
                        tempText = PR_smprintf
                                (" %02X", (0x0FF&((char *)(array->array))[i]));

                        if (tempText == NULL){
                                PKIX_ERROR(PKIX_PRSMPRINTFFAILED);
                        }

                        PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
                        outputLen += PL_strlen(tempText);

                        PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
                        stringText = PL_strcat(stringText, tempText);

                        PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
                        PR_smprintf_free(tempText);
                        tempText = NULL;
                }

                stringText[outputLen++] = ']';
                stringText[outputLen] = 0;

                PKIX_CHECK(PKIX_PL_String_Create
                        (PKIX_ESCASCII,
                        stringText,
                        0,
                        pString,
                        plContext),
                        PKIX_COULDNOTCREATESTRING);
        }

cleanup:

        PKIX_FREE(stringText);
        PKIX_RETURN(BYTEARRAY);
}
Пример #17
0
/*
 * FUNCTION: pkix_pl_oidBytes2Ascii
 * DESCRIPTION:
 *
 *  Converts the DER encoding of an OID pointed to by "secItem" to an ASCII
 *  representation and stores it at "pAscii". The ASCII representation is
 *  guaranteed to end with a NUL character. The input SECItem must contain
 *  non-NULL data and must have a positive length.
 *
 *  Example: the six bytes {2a 86 48 86 f7 0d} represent the
 *  four integer tokens {1, 2, 840, 113549}, which we will convert
 *  into ASCII yielding "1.2.840.113549"
 *
 *  The return value "pAscii" is not reference-counted and will need to
 *  be freed with PKIX_PL_Free.
 *
 * PARAMETERS
 *  "secItem"
 *      Address of SECItem which contains bytes and length of DER encoding.
 *      Must be non-NULL.
 *  "pAscii"
 *      Address where object pointer 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 OID 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_oidBytes2Ascii(
        SECItem *secItem,
        char **pAscii,
        void *plContext)
{
        char *data = NULL;
        PKIX_UInt32 *tokens = NULL;
        PKIX_UInt32 token = 0;
        PKIX_UInt32 numBytes = 0;
        PKIX_UInt32 numTokens = 0;
        PKIX_UInt32 i = 0, x = 0, y = 0;
        PKIX_UInt32 index = 0;
        char *asciiString = NULL;

        PKIX_ENTER(OID, "pkix_pl_oidBytes2Ascii");
        PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data);

        if (secItem->len == 0) {
                PKIX_ERROR_FATAL(PKIX_OIDBYTES2ASCIIDATALENGTHZERO);
        }

        data = (char *)(secItem->data);
        numBytes = secItem->len;
        numTokens = 0;

        /* calculate how many integer tokens are represented by the bytes. */
        for (i = 0; i < numBytes; i++){
                if ((data[i] & 0x080) == 0){
                        numTokens++;
                }
        }

        /* if we are unable to retrieve any tokens at all, we throw an error */
        if (numTokens == 0){
                PKIX_ERROR(PKIX_INVALIDDERENCODINGFOROID);
        }

        /* add one more token b/c the first byte always contains two tokens */
        numTokens++;

        /* allocate space for array of integers */
        PKIX_CHECK(PKIX_PL_Malloc
                    (numTokens * sizeof (PKIX_UInt32),
                    (void **)&tokens,
                    plContext),
                    PKIX_MALLOCFAILED);

        /* populate array of integers */
        for (i = 0; i < numTokens; i++){

                /* retrieve integer token */
                PKIX_CHECK(pkix_pl_getOIDToken
                            (data, index, &token, &index, plContext),
                            PKIX_GETOIDTOKENFAILED);

                if (i == 0){

                        /*
                         * special case: the first DER-encoded byte represents
                         * two tokens. We take advantage of fact that first
                         * token must be 0, 1, or 2; and second token must be
                         * between {0, 39} inclusive if first token is 0 or 1.
                         */

                        if (token < 40)
                                x = 0;
                        else if (token < 80)
                                x = 1;
                        else
                                x = 2;
                        y = token - (x * 40);

                        tokens[0] = x;
                        tokens[1] = y;
                        i++;
                } else {
                        tokens[i] = token;
                }
        }

        /* convert array of integers to ASCII */
        PKIX_CHECK(pkix_pl_helperBytes2Ascii
                    (tokens, numTokens, &asciiString, plContext),
                    PKIX_HELPERBYTES2ASCIIFAILED);

        *pAscii = asciiString;

cleanup:

        PKIX_FREE(tokens);
        PKIX_RETURN(OID);

}
Пример #18
0
/*
 * FUNCTION: pkix_pl_CollectionCertStoreContext_PopulateCRL
 * DESCRIPTION:
 *
 *  Create list of CRLs from *.crl files at directory specified in dirName,
 *  Not recursive to sub-dirctory. Also assume the directory contents are
 *  not changed dynamically.
 *
 * PARAMETERS
 *  "colCertStoreContext" - Address of CollectionCertStoreContext
 *              where the dirName is specified and where the return
 *              CRLs are stored as a list. Must be non-NULL.
 *  "plContext" - Platform-specific context pointer.
 *
 * THREAD SAFETY:
 *  Not Thread Safe - A lock at top level is required.
 *
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a CollectionCertStoreContext Error if the function fails in
 *              a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */
static PKIX_Error *
pkix_pl_CollectionCertStoreContext_PopulateCRL(
        PKIX_PL_CollectionCertStoreContext *colCertStoreContext,
        void *plContext)
{
        PKIX_List *crlList = NULL;
        PKIX_PL_CRL *crlItem = NULL;
        char *dirName = NULL;
        char *pathName = NULL;
        PKIX_UInt32 dirNameLen = 0;
        PRErrorCode prError = 0;
        PRDir *dir = NULL;
        PRDirEntry *dirEntry = NULL;

        PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
                    "pkix_pl_CollectionCertStoreContext_PopulateCRL");
        PKIX_NULLCHECK_ONE(colCertStoreContext);

        /* convert directory to ascii */

        PKIX_CHECK(PKIX_PL_String_GetEncoded
                    (colCertStoreContext->storeDir,
                    PKIX_ESCASCII,
                    (void **)&dirName,
                    &dirNameLen,
                    plContext),
                    PKIX_STRINGGETENCODEDFAILED);

        /* create CRL list, if no CRL file, should return an empty list */

        PKIX_CHECK(PKIX_List_Create(&crlList, plContext),
                    PKIX_LISTCREATEFAILED);

        /* open directory and read in .crl files */

        PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_OpenDir.\n");
        dir = PR_OpenDir(dirName);

        if (!dir) {
                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG
                        ("\t\t Directory Name:%s\n", dirName);
                PKIX_ERROR(PKIX_CANNOTOPENCOLLECTIONCERTSTORECONTEXTDIRECTORY);
        }

        PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_ReadDir.\n");
        dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH);

        if (!dirEntry) {
                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Empty directory.\n");
                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_GetError.\n");
                prError = PR_GetError();
        }

        PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_SetError.\n");
        PR_SetError(0, 0);

        while (dirEntry != NULL && prError == 0) {
                if (PL_strrstr(dirEntry->name, ".crl") ==
                    dirEntry->name + PL_strlen(dirEntry->name) - 4) {

                        PKIX_CHECK_ONLY_FATAL
                                (PKIX_PL_Malloc
                                (dirNameLen + PL_strlen(dirEntry->name) + 2,
                                (void **)&pathName,
                                plContext),
                                PKIX_MALLOCFAILED);

                        if ((!PKIX_ERROR_RECEIVED) && (pathName != NULL)){

                                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                                    ("\t\t Calling PL_strcpy for dirName.\n");
                                PL_strcpy(pathName, dirName);
                                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                                    ("\t\t Calling PL_strcat for dirName.\n");
                                PL_strcat(pathName, "/");
                                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                                        ("\t\t Calling PL_strcat for /.\n");
                                PL_strcat(pathName, dirEntry->name);

                        PKIX_CHECK_ONLY_FATAL
                                (pkix_pl_CollectionCertStoreContext_CreateCRL
                                (pathName, &crlItem, plContext),
                                PKIX_COLLECTIONCERTSTORECONTEXTCREATECRLFAILED);

                                if (!PKIX_ERROR_RECEIVED){
                                        PKIX_CHECK_ONLY_FATAL
                                                (PKIX_List_AppendItem
                                                (crlList,
                                                (PKIX_PL_Object *)crlItem,
                                                plContext),
                                                PKIX_LISTAPPENDITEMFAILED);
                                }
                        }

                        PKIX_DECREF(crlItem);
                        PKIX_FREE(pathName);
                }

                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_SetError.\n");
                PR_SetError(0, 0);

                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_ReadDir.\n");
                dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH);

                if (!dirEntry) {
                    PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_GetError.\n");
                    prError = PR_GetError();
                }
        }

        if ((prError != 0) && (prError != PR_NO_MORE_FILES_ERROR)) {
                PKIX_ERROR(PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED);
        }

        PKIX_CHECK(PKIX_List_SetImmutable(crlList, plContext),
                    PKIX_LISTSETIMMUTABLEFAILED);

        PKIX_INCREF(crlList);
        colCertStoreContext->crlList = crlList;

cleanup:
        if (dir) {
                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_CloseDir.\n");
                PR_CloseDir(dir);
        }

        PKIX_FREE(pathName);
        PKIX_FREE(dirName);

        if (PKIX_ERROR_RECEIVED){
                PKIX_DECREF(crlList);
        }

        PKIX_DECREF(crlItem);
        PKIX_DECREF(crlList);

        PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
}
Пример #19
0
/*
 * FUNCTION: pkix_pl_helperBytes2Ascii
 * DESCRIPTION:
 *
 *  Converts an array of integers pointed to by "tokens" with a length of
 *  "numTokens", to an ASCII string consisting of those integers with dots in
 *  between them and stores the result at "pAscii". The ASCII representation is
 *  guaranteed to end with a NUL character. This is particularly useful for
 *  OID's and IP Addresses.
 *
 *  The return value "pAscii" is not reference-counted and will need to
 *  be freed with PKIX_PL_Free.
 *
 * PARAMETERS
 *  "tokens"
 *      Address of array of integers. Must be non-NULL.
 *  "numTokens"
 *      Length of array of integers. Must be non-zero.
 *  "pAscii"
 *      Address where object pointer 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 Object 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_helperBytes2Ascii(
        PKIX_UInt32 *tokens,
        PKIX_UInt32 numTokens,
        char **pAscii,
        void *plContext)
{
        char *tempString = NULL;
        char *outputString = NULL;
        char *format = "%d";
        PKIX_UInt32 i = 0;
        PKIX_UInt32 outputLen = 0;
        PKIX_Int32 error;

        PKIX_ENTER(OBJECT, "pkix_pl_helperBytes2Ascii");
        PKIX_NULLCHECK_TWO(tokens, pAscii);

        if (numTokens == 0) {
                PKIX_ERROR_FATAL(PKIX_HELPERBYTES2ASCIINUMTOKENSZERO);
        }

        /*
         * tempString will hold the string representation of a PKIX_UInt32 type
         * The maximum value that can be held by an unsigned 32-bit integer
         * is (2^32 - 1) = 4294967295 (which is ten digits long)
         * Since tempString will hold the string representation of a
         * PKIX_UInt32, we allocate 11 bytes for it (1 byte for '\0')
         */

        PKIX_CHECK(PKIX_PL_Malloc
                    (MAX_DIGITS_32 + 1, (void **)&tempString, plContext),
                    PKIX_MALLOCFAILED);

        for (i = 0; i < numTokens; i++){
                PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n");
                error = PR_snprintf(tempString,
                                    MAX_DIGITS_32 + 1,
                                    format,
                                    tokens[i]);
                if (error == -1){
                        PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
                }

                PKIX_OBJECT_DEBUG("\tCalling PL_strlen).\n");
                outputLen += PL_strlen(tempString);

                /* Include a dot to separate each number */
                outputLen++;
        }

        /* Allocate space for the destination string */
        PKIX_CHECK(PKIX_PL_Malloc
                    (outputLen, (void **)&outputString, plContext),
                    PKIX_MALLOCFAILED);

        *outputString = '\0';

        /* Concatenate all strings together */
        for (i = 0; i < numTokens; i++){

                PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n");
                error = PR_snprintf(tempString,
                                    MAX_DIGITS_32 + 1,
                                    format,
                                    tokens[i]);
                if (error == -1){
                        PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
                }

                PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n");
                (void) PL_strcat(outputString, tempString);

                /* we don't want to put a "." at the very end */
                if (i < (numTokens - 1)){
                        PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n");
                        (void) PL_strcat(outputString, ".");
                }
        }

        /* Ensure output string ends with terminating null */
        outputString[outputLen-1] = '\0';

        *pAscii = outputString;
        outputString = NULL;

cleanup:
        
        PKIX_FREE(outputString);
        PKIX_FREE(tempString);

        PKIX_RETURN(OBJECT);

}
Пример #20
0
/*
 * FUNCTION: pkix_pl_GeneralName_Create
 * DESCRIPTION:
 *
 *  Creates new GeneralName which represents the CERTGeneralName pointed to by
 *  "nssAltName" and stores it at "pGenName".
 *
 * PARAMETERS:
 *  "nssAltName"
 *      Address of CERTGeneralName. Must be non-NULL.
 *  "pGenName"
 *      Address where object pointer 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 GeneralName 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_GeneralName_Create(
        CERTGeneralName *nssAltName,
        PKIX_PL_GeneralName **pGenName,
        void *plContext)
{
        PKIX_PL_GeneralName *genName = NULL;
        PKIX_PL_X500Name *pkixDN = NULL;
        PKIX_PL_OID *pkixOID = NULL;
        OtherName *otherName = NULL;
        CERTGeneralNameList *nssGenNameList = NULL;
        CERTGeneralNameType nameType;
        SECItem *secItem = NULL;
        char *asciiName = NULL;
        SECStatus rv;

        PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Create");
        PKIX_NULLCHECK_TWO(nssAltName, pGenName);

        /* create a PKIX_PL_GeneralName object */
        PKIX_CHECK(PKIX_PL_Object_Alloc
                    (PKIX_GENERALNAME_TYPE,
                    sizeof (PKIX_PL_GeneralName),
                    (PKIX_PL_Object **)&genName,
                    plContext),
                    PKIX_COULDNOTCREATEOBJECT);

        nameType = nssAltName->type;

        /*
         * We use CERT_CreateGeneralNameList to create just one CERTGeneralName
         * item for memory allocation reason. If we want to just create one
         * item, we have to use the calling path CERT_NewGeneralName, then
         * CERT_CopyOneGeneralName. With this calling path, if we pass
         * the arena argument as NULL, in CERT_CopyOneGeneralName's subsequent
         * call to CERT_CopyName, it assumes arena should be valid, hence
         * segmentation error (not sure this is a NSS bug, certainly it is
         * not consistent). But on the other hand, we don't want to keep an
         * arena record here explicitely for every PKIX_PL_GeneralName.
         * So I concluded it is better to use CERT_CreateGeneralNameList,
         * which keeps an arena pointer in its data structure and also masks
         * out details calls from this libpkix level.
         */

        PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
        nssGenNameList = CERT_CreateGeneralNameList(nssAltName);

        if (nssGenNameList == NULL) {
                PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
        }

        genName->nssGeneralNameList = nssGenNameList;

        /* initialize fields */
        genName->type = nameType;
        genName->directoryName = NULL;
        genName->OthName = NULL;
        genName->other = NULL;
        genName->oid = NULL;

        switch (nameType){
        case certOtherName:

                PKIX_CHECK(pkix_pl_OtherName_Create
                            (nssAltName, &otherName, plContext),
                            PKIX_OTHERNAMECREATEFAILED);

                genName->OthName = otherName;
                break;

        case certDirectoryName:

                PKIX_CHECK(pkix_pl_DirectoryName_Create
                            (nssAltName, &pkixDN, plContext),
                            PKIX_DIRECTORYNAMECREATEFAILED);

                genName->directoryName = pkixDN;
                break;
        case certRegisterID:

                PKIX_CHECK(pkix_pl_oidBytes2Ascii
                            (&nssAltName->name.other, &asciiName, plContext),
                            PKIX_OIDBYTES2ASCIIFAILED);

                PKIX_CHECK(PKIX_PL_OID_Create(asciiName, &pkixOID, plContext),
                            PKIX_OIDCREATEFAILED);

                genName->oid = pkixOID;
                break;
        case certDNSName:
        case certEDIPartyName:
        case certIPAddress:
        case certRFC822Name:
        case certX400Address:
        case certURI:

                PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_AllocItem).\n");
                secItem = SECITEM_AllocItem(NULL, NULL, 0);
                if (secItem == NULL){
                        PKIX_ERROR(PKIX_OUTOFMEMORY);
                }

                PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
                rv = SECITEM_CopyItem(NULL, secItem, &nssAltName->name.other);
                if (rv != SECSuccess) {
                        PKIX_ERROR(PKIX_OUTOFMEMORY);
                }

                genName->other = secItem;
                break;
        default:
                PKIX_ERROR(PKIX_NAMETYPENOTSUPPORTED);
        }

        *pGenName = genName;
cleanup:

        PKIX_FREE(asciiName);

        if (PKIX_ERROR_RECEIVED){
                PKIX_DECREF(genName);
                if (secItem){
                        PKIX_GENERALNAME_DEBUG
                                ("\t\tCalling SECITEM_FreeItem).\n");
                        SECITEM_FreeItem(secItem, PR_TRUE);
                        secItem = NULL;
                }
        }

        PKIX_RETURN(GENERALNAME);
}
Пример #21
0
/*
 * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h)
 */
PKIX_Error *
PKIX_PL_Object_Alloc(
        PKIX_TYPENUM objType,
        PKIX_UInt32 size,
        PKIX_PL_Object **pObject,
        void *plContext)
{
        PKIX_PL_Object *object = NULL;
        pkix_ClassTable_Entry *ctEntry = NULL;

        PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc");
        PKIX_NULLCHECK_ONE(pObject);

        /*
         * We need to ensure that user-defined types have been registered.
         * All system types have already been registered by PKIX_PL_Initialize.
         */

        if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type */
#ifdef PKIX_USER_OBJECT_TYPE
                PKIX_Boolean typeRegistered;
                PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
                PR_Lock(classTableLock);
                pkixErrorResult = pkix_pl_PrimHashTable_Lookup
                        (classTable,
                        (void *)&objType,
                        objType,
                        NULL,
                        (void **)&ctEntry,
                        plContext);
                PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
                PR_Unlock(classTableLock);
                if (pkixErrorResult){
                        PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE);
                }

                typeRegistered = (ctEntry != NULL);

                if (!typeRegistered) {
                        PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT);
                }
#else
                PORT_Assert (0);
                pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
                pkixErrorClass = PKIX_FATAL_ERROR;
                goto cleanup;
#endif /* PKIX_USER_OBJECT_TYPE */
        } else {
                ctEntry = &systemClasses[objType];
        }
        
        PORT_Assert(size == ctEntry->typeObjectSize);

        /* Allocate space for the object header and the requested size */
#ifdef PKIX_OBJECT_LEAK_TEST       
        PKIX_CHECK(PKIX_PL_Calloc
                    (1,
                    ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
                    (void **)&object,
                    plContext),
                    PKIX_MALLOCFAILED);
#else
        PKIX_CHECK(PKIX_PL_Malloc
                    (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
                    (void **)&object,
                    plContext),
                    PKIX_MALLOCFAILED);
#endif /* PKIX_OBJECT_LEAK_TEST */

        /* Initialize all object fields */
        object->magicHeader = PKIX_MAGIC_HEADER;
        object->type = objType;
        object->references = 1; /* Default to a single reference */
        object->stringRep = NULL;
        object->hashcode = 0;
        object->hashcodeCached = 0;

        /* Cannot use PKIX_PL_Mutex because it depends on Object */
        /* Using NSPR Locks instead */
        PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n");
        object->lock = PR_NewLock();
        if (object->lock == NULL) {
                PKIX_ERROR_ALLOC_ERROR();
        }

        PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");


        /* Return a pointer to the user data. Need to offset by object size */
        *pObject = object + 1;
        object = NULL;

        /* Atomically increment object counter */
        PR_ATOMIC_INCREMENT(&ctEntry->objCounter);

cleanup:

        PKIX_FREE(object);

        PKIX_RETURN(OBJECT);
}
Пример #22
0
/*
 * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h)
 */
PKIX_Error *
PKIX_PL_CRL_Create(
    PKIX_PL_ByteArray *byteArray,
    PKIX_PL_CRL **pCrl,
    void *plContext)
{
    CERTSignedCrl *nssSignedCrl = NULL;
    SECItem *derCrlItem = NULL;
    void *derBytes = NULL;
    PKIX_UInt32 derLength;
    PKIX_PL_CRL *crl = NULL;

    PKIX_ENTER(CRL, "PKIX_PL_CRL_Create");
    PKIX_NULLCHECK_TWO(byteArray, pCrl);

    PKIX_CHECK(PKIX_PL_ByteArray_GetLength
               (byteArray, &derLength, plContext),
               PKIX_BYTEARRAYGETLENGTHFAILED);

    if (derLength == 0) {
        PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING);
    }

    PKIX_CHECK(PKIX_PL_ByteArray_GetPointer
               (byteArray, &derBytes, plContext),
               PKIX_BYTEARRAYGETPOINTERFAILED);

    PKIX_CRL_DEBUG("\t\tCalling SECITEM_AllocItem\n");
    derCrlItem = SECITEM_AllocItem(NULL, NULL, derLength);
    if (derCrlItem == NULL) {
        PKIX_ERROR(PKIX_OUTOFMEMORY);
    }

    PKIX_CRL_DEBUG("\t\tCalling PORT_Memcpy\n");
    (void) PORT_Memcpy(derCrlItem->data, derBytes, derLength);

    PKIX_CRL_DEBUG("\t\tCalling CERT_DecodeDERCrl\n");
    nssSignedCrl = CERT_DecodeDERCrl(NULL, derCrlItem, SEC_CRL_TYPE);
    if (nssSignedCrl == NULL) {
        PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED);
    }

    PKIX_CHECK(pkix_pl_CRL_CreateWithSignedCRL
               (nssSignedCrl, &crl, plContext),
               PKIX_CRLCREATEWITHSIGNEDCRLFAILED);

    *pCrl = crl;

cleanup:

    if (derCrlItem != NULL) {
        PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n");
        SECITEM_FreeItem(derCrlItem, PKIX_TRUE);
        derCrlItem = NULL;
    }

    if (PKIX_ERROR_RECEIVED) {
        if (nssSignedCrl != NULL) {
            PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n");
            CERT_DestroyCrl(nssSignedCrl);
            nssSignedCrl = NULL;
        }

        PKIX_DECREF(crl);
    }

    PKIX_FREE(derBytes);

    PKIX_RETURN(CRL);
}
Пример #23
0
/*
 * FUNCTION: pkix_pl_GeneralName_ToString_Helper
 * DESCRIPTION:
 *
 *  Helper function that creates a string representation of the GeneralName
 *  pointed to by "name" and stores it at "pString" Different mechanisms are
 *  used to create the string, depending on the type of the GeneralName.
 *
 * PARAMETERS
 *  "name"
 *      Address of GeneralName whose string representation is desired.
 *      Must be non-NULL.
 *  "pString"
 *      Address where object pointer 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 GeneralName Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */
static PKIX_Error *
pkix_pl_GeneralName_ToString_Helper(
        PKIX_PL_GeneralName *name,
        PKIX_PL_String **pString,
        void *plContext)
{
        PKIX_PL_X500Name *pkixDN = NULL;
        PKIX_PL_OID *pkixOID = NULL;
        char *x400AsciiName = NULL;
        char *ediPartyName = NULL;
        char *asciiName = NULL;

        PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_ToString_Helper");
        PKIX_NULLCHECK_TWO(name, pString);

        switch (name->type) {
        case certRFC822Name:
        case certDNSName:
        case certURI:
                /*
                 * Note that we can't use PKIX_ESCASCII here because
                 * name->other->data is not guaranteed to be null-terminated.
                 */

                PKIX_NULLCHECK_ONE(name->other);

                PKIX_CHECK(PKIX_PL_String_Create(PKIX_UTF8,
                                                (name->other)->data,
                                                (name->other)->len,
                                                pString,
                                                plContext),
                            PKIX_STRINGCREATEFAILED);
                break;
        case certEDIPartyName:
                /* XXX print out the actual bytes */
                ediPartyName = "EDIPartyName: <DER-encoded value>";
                PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
                                                ediPartyName,
                                                0,
                                                pString,
                                                plContext),
                            PKIX_STRINGCREATEFAILED);
                break;
        case certX400Address:
                /* XXX print out the actual bytes */
                x400AsciiName = "X400Address: <DER-encoded value>";
                PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
                                                x400AsciiName,
                                                0,
                                                pString,
                                                plContext),
                            PKIX_STRINGCREATEFAILED);
                break;
        case certIPAddress:
                PKIX_CHECK(pkix_pl_ipAddrBytes2Ascii
                            (name->other, &asciiName, plContext),
                            PKIX_IPADDRBYTES2ASCIIFAILED);

                PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
                                                asciiName,
                                                0,
                                                pString,
                                                plContext),
                            PKIX_STRINGCREATEFAILED);
                break;
        case certOtherName:
                PKIX_NULLCHECK_ONE(name->OthName);

                /* we only print type-id - don't know how to print value */
                /* XXX print out the bytes of the value */
                PKIX_CHECK(pkix_pl_oidBytes2Ascii
                            (&name->OthName->oid, &asciiName, plContext),
                            PKIX_OIDBYTES2ASCIIFAILED);

                PKIX_CHECK(PKIX_PL_String_Create
                            (PKIX_ESCASCII,
                            asciiName,
                            0,
                            pString,
                            plContext),
                            PKIX_STRINGCREATEFAILED);
                break;
        case certRegisterID:
                pkixOID = name->oid;
                PKIX_CHECK(PKIX_PL_Object_ToString
                            ((PKIX_PL_Object *)pkixOID, pString, plContext),
                            PKIX_OIDTOSTRINGFAILED);
                break;
        case certDirectoryName:
                pkixDN = name->directoryName;
                PKIX_CHECK(PKIX_PL_Object_ToString
                            ((PKIX_PL_Object *)pkixDN, pString, plContext),
                            PKIX_X500NAMETOSTRINGFAILED);
                break;
        default:
                PKIX_ERROR
                        (PKIX_TOSTRINGFORTHISGENERALNAMETYPENOTSUPPORTED);
        }

cleanup:

        PKIX_FREE(asciiName);

        PKIX_RETURN(GENERALNAME);
}
Пример #24
0
/*
 * FUNCTION: PKIX_PL_GeneralName_Create (see comments in pkix_pl_pki.h)
 */
PKIX_Error *
PKIX_PL_GeneralName_Create(
        PKIX_UInt32 nameType,
        PKIX_PL_String *stringRep,
        PKIX_PL_GeneralName **pGName,
        void *plContext)
{
        PKIX_PL_X500Name *pkixDN = NULL;
        PKIX_PL_OID *pkixOID = NULL;
        SECItem *secItem = NULL;
        char *asciiString = NULL;
        PKIX_UInt32 length = 0;
        PKIX_PL_GeneralName *genName = NULL;
        CERTGeneralName *nssGenName = NULL;
        CERTGeneralNameList *nssGenNameList = NULL;
        CERTName *nssCertName = NULL;
        PLArenaPool *arena = NULL;

        PKIX_ENTER(GENERALNAME, "PKIX_PL_GeneralName_Create");
        PKIX_NULLCHECK_TWO(pGName, stringRep);

        PKIX_CHECK(PKIX_PL_String_GetEncoded
                    (stringRep,
                    PKIX_ESCASCII,
                    (void **)&asciiString,
                    &length,
                    plContext),
                    PKIX_STRINGGETENCODEDFAILED);

        /* Create a temporary CERTGeneralName */
        PKIX_GENERALNAME_DEBUG("\t\tCalling PL_strlen).\n");
        length = PL_strlen(asciiString);
        PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_AllocItem).\n");
        secItem = SECITEM_AllocItem(NULL, NULL, length);
        PKIX_GENERALNAME_DEBUG("\t\tCalling PORT_Memcpy).\n");
        (void) PORT_Memcpy(secItem->data, asciiString, length);
        PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena).\n");
        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (arena == NULL) {
                PKIX_ERROR(PKIX_OUTOFMEMORY);
        }
        PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_NewGeneralName).\n");
        nssGenName = CERT_NewGeneralName(arena, nameType);
        if (nssGenName == NULL) {
                PKIX_ERROR(PKIX_ALLOCATENEWCERTGENERALNAMEFAILED);
        }

        switch (nameType) {
        case certRFC822Name:
        case certDNSName:
        case certURI:
                nssGenName->name.other = *secItem;
                break;

        case certDirectoryName:

                PKIX_CHECK(PKIX_PL_X500Name_Create
                            (stringRep, &pkixDN, plContext),
                            PKIX_X500NAMECREATEFAILED);

                PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_AsciiToName).\n");
                nssCertName = CERT_AsciiToName(asciiString);
                nssGenName->name.directoryName = *nssCertName;
                break;

        case certRegisterID:
                PKIX_CHECK(PKIX_PL_OID_Create
                            (asciiString, &pkixOID, plContext),
                            PKIX_OIDCREATEFAILED);
                nssGenName->name.other = *secItem;
                break;
        default:
                /* including IPAddress, EDIPartyName, OtherName, X400Address */
                PKIX_ERROR(PKIX_UNABLETOCREATEGENERALNAMEOFTHISTYPE);
        }

        /* create a PKIX_PL_GeneralName object */
        PKIX_CHECK(PKIX_PL_Object_Alloc
                    (PKIX_GENERALNAME_TYPE,
                    sizeof (PKIX_PL_GeneralName),
                    (PKIX_PL_Object **)&genName,
                    plContext),
                    PKIX_COULDNOTCREATEOBJECT);

        /* create a CERTGeneralNameList */
        nssGenName->type = nameType;
        PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
        nssGenNameList = CERT_CreateGeneralNameList(nssGenName);
        if (nssGenNameList == NULL) {
                PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
        }
        genName->nssGeneralNameList = nssGenNameList;

        /* initialize fields */
        genName->type = nameType;
        genName->directoryName = pkixDN;
        genName->OthName = NULL;
        genName->other = secItem;
        genName->oid = pkixOID;

        *pGName = genName;
cleanup:

        PKIX_FREE(asciiString);

        if (nssCertName != NULL) {
                PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyName).\n");
                CERT_DestroyName(nssCertName);
        }

        if (arena){ /* will free nssGenName */
                PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
                PORT_FreeArena(arena, PR_FALSE);
        }

        if (PKIX_ERROR_RECEIVED){
                PKIX_DECREF(pkixDN);
                PKIX_DECREF(pkixOID);

                PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
                if (secItem){
                        SECITEM_FreeItem(secItem, PR_TRUE);
                        secItem = NULL;
                }
        }

        PKIX_RETURN(GENERALNAME);
}