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