/* * FUNCTION: pkix_List_GetElement * DESCRIPTION: * * Copies the "list"'s element at "index" into "element". The input List must * be the header of the List (as opposed to being an element of the List). The * index counts from zero and must be less than the List's length. This * function does NOT increment the reference count of the List element since * the returned element's reference will not be stored by the calling * function. * * PARAMETERS: * "list" * Address of List (must be header) to get element from. Must be non-NULL. * "index" * Index of list to get element from. Must be less than List's length. * "pElement" * Address where object pointer will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Conditionally 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_List_GetElement( PKIX_List *list, PKIX_UInt32 index, PKIX_List **pElement, void *plContext) { PKIX_List *iterator = NULL; PKIX_UInt32 length; PKIX_UInt32 position = 0; PKIX_ENTER(LIST, "pkix_List_GetElement"); PKIX_NULLCHECK_TWO(list, pElement); if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } length = list->length; if (index >= length) { PKIX_ERROR(PKIX_INDEXOUTOFBOUNDS); } for (iterator = list; position++ <= index; iterator = iterator->next) ; (*pElement) = iterator; cleanup: PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_pl_HttpCertStore_ProcessCertResponse * DESCRIPTION: * * This function verifies that the response code pointed to by "responseCode" * and the content type pointed to by "responseContentType" are as expected, * and then decodes the data pointed to by "responseData", of length * "responseDataLen", into a List of Certs, possibly empty, which is returned * at "pCertList". * * PARAMETERS: * "responseCode" * The value of the HTTP response code. * "responseContentType" * The address of the Content-type string. Must be non-NULL. * "responseData" * The address of the message data. Must be non-NULL. * "responseDataLen" * The length of the message data. * "pCertList" * The address of the List that is created. 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 HttpCertStore 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_HttpCertStore_ProcessCertResponse( PRUint16 responseCode, const char *responseContentType, const char *responseData, PRUint32 responseDataLen, PKIX_List **pCertList, void *plContext) { callbackContext cbContext; PKIX_ENTER(HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStore_ProcessCertResponse"); cbContext.error = NULL; cbContext.plContext = plContext; cbContext.pkixCertList = NULL; PKIX_NULLCHECK_ONE(pCertList); if (responseCode != 200) { PKIX_ERROR(PKIX_BADHTTPRESPONSE); } /* check that response type is application/pkcs7-mime */ if (responseContentType == NULL) { PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE); } if (responseData == NULL) { PKIX_ERROR(PKIX_NORESPONSEDATAINHTTPRESPONSE); } PKIX_CHECK( PKIX_List_Create(&cbContext.pkixCertList, plContext), PKIX_LISTCREATEFAILED); PKIX_CHECK_ONLY_FATAL( pkix_pl_HttpCertStore_DecodeCertPackage(responseData, responseDataLen, certCallback, &cbContext, plContext), PKIX_HTTPCERTSTOREDECODECERTPACKAGEFAILED); if (cbContext.error) { /* Aborting on a fatal error(See certCallback fn) */ pkixErrorResult = cbContext.error; goto cleanup; } *pCertList = cbContext.pkixCertList; cbContext.pkixCertList = NULL; cleanup: PKIX_DECREF(cbContext.pkixCertList); PKIX_RETURN(HTTPCERTSTORECONTEXT); }
/* * FUNCTION: PKIX_List_InsertItem (see comments in pkix_util.h) */ PKIX_Error * PKIX_List_InsertItem( PKIX_List *list, PKIX_UInt32 index, PKIX_PL_Object *item, void *plContext) { PKIX_List *element = NULL; PKIX_List *newElem = NULL; PKIX_ENTER(LIST, "PKIX_List_InsertItem"); PKIX_NULLCHECK_ONE(list); if (list->immutable){ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); } if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } /* Create a new list object */ PKIX_CHECK(pkix_List_Create_Internal(PKIX_FALSE, &newElem, plContext), PKIX_LISTCREATEINTERNALFAILED); if (list->length) { PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), PKIX_LISTGETELEMENTFAILED); /* Copy the old element's contents into the new element */ newElem->item = element->item; /* Add new item to the list */ PKIX_INCREF(item); element->item = item; /* Set the new element's next pointer to the old element's next */ newElem->next = element->next; /* Set the old element's next pointer to the new element */ element->next = newElem; newElem = NULL; } else { PKIX_INCREF(item); newElem->item = item; newElem->next = NULL; list->next = newElem; newElem = NULL; } list->length++; PKIX_CHECK(PKIX_PL_Object_InvalidateCache ((PKIX_PL_Object *)list, plContext), PKIX_OBJECTINVALIDATECACHEFAILED); cleanup: PKIX_DECREF(newElem); PKIX_RETURN(LIST); }
/* * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_CRL_VerifyUpdateTime( PKIX_PL_CRL *crl, PKIX_PL_Date *date, PKIX_Boolean *pResult, void *plContext) { PRTime timeToCheck; PRTime nextUpdate; PRTime lastUpdate; SECStatus status; CERTCrl *nssCrl = NULL; SECItem *nextUpdateDer = NULL; PKIX_Boolean haveNextUpdate = PR_FALSE; PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime"); PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult); nssCrl = &(crl->nssSignedCrl->crl); PKIX_CRL_DEBUG("\t\tCalling DER_DecodeTimeChoice on date\n"); status = DER_DecodeTimeChoice(&timeToCheck, &(date->nssTime)); if (status != SECSuccess) { PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED); } /* nextUpdate can be NULL. Checking before using it */ nextUpdateDer = &nssCrl->nextUpdate; if (nextUpdateDer->data && nextUpdateDer->len) { haveNextUpdate = PR_TRUE; status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer); if (status != SECSuccess) { PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED); } } status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate)); if (status != SECSuccess) { PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED); } if (!haveNextUpdate || nextUpdate < timeToCheck) { *pResult = PKIX_FALSE; goto cleanup; } if (lastUpdate <= timeToCheck) { *pResult = PKIX_TRUE; } else { *pResult = PKIX_FALSE; } cleanup: 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_List_AppendItem (see comments in pkix_util.h) */ PKIX_Error * PKIX_List_AppendItem( PKIX_List *list, PKIX_PL_Object *item, void *plContext) { PKIX_List *lastElement = NULL; PKIX_List *newElement = NULL; PKIX_UInt32 length, i; PKIX_ENTER(LIST, "PKIX_List_AppendItem"); PKIX_NULLCHECK_ONE(list); if (list->immutable){ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); } if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } length = list->length; /* find last element of list and create new element there */ lastElement = list; for (i = 0; i < length; i++){ lastElement = lastElement->next; } PKIX_CHECK(pkix_List_Create_Internal (PKIX_FALSE, &newElement, plContext), PKIX_LISTCREATEINTERNALFAILED); PKIX_INCREF(item); newElement->item = item; PKIX_CHECK(PKIX_PL_Object_InvalidateCache ((PKIX_PL_Object *)list, plContext), PKIX_OBJECTINVALIDATECACHEFAILED); lastElement->next = newElement; newElement = NULL; list->length += 1; cleanup: PKIX_DECREF(newElement); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_pl_HttpCertStore_CreateRequestSession * DESCRIPTION: * * This function takes elements from the HttpCertStoreContext pointed to by * "context" (path, client, and serverSession) and creates a RequestSession. * See the HTTPClient API described in ocspt.h for further details. * * PARAMETERS: * "context" * The address of the HttpCertStoreContext. 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 HttpCertStore 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_HttpCertStore_CreateRequestSession( PKIX_PL_HttpCertStoreContext *context, void *plContext) { const SEC_HttpClientFcnV1 *hcv1 = NULL; SECStatus rv = SECFailure; char *pathString = NULL; PKIX_ENTER (HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStore_CreateRequestSession"); PKIX_NULLCHECK_TWO(context, context->serverSession); pathString = PR_smprintf("%s", context->path); if (context->client->version == 1) { hcv1 = &(context->client->fcnTable.ftable1); if (context->requestSession != NULL) { PKIX_PL_NSSCALL(HTTPCERTSTORECONTEXT, hcv1->freeFcn, (context->requestSession)); context->requestSession = 0; } PKIX_PL_NSSCALLRV (HTTPCERTSTORECONTEXT, rv, hcv1->createFcn, (context->serverSession, "http", pathString, "GET", PR_TicksPerSecond() * 60, &(context->requestSession))); if (rv != SECSuccess) { if (pathString != NULL) { PORT_Free(pathString); } PKIX_ERROR(PKIX_HTTPSERVERERROR); } } else { PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); } cleanup: PKIX_RETURN(HTTPCERTSTORECONTEXT); }
/* * 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 derItem, *derCrl = NULL; PKIX_PL_CRL *crl = NULL; PKIX_ENTER(CRL, "PKIX_PL_CRL_Create"); PKIX_NULLCHECK_TWO(byteArray, pCrl); if (byteArray->length == 0){ PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING); } derItem.type = siBuffer; derItem.data = byteArray->array; derItem.len = byteArray->length; derCrl = SECITEM_DupItem(&derItem); if (!derCrl) { PKIX_ERROR(PKIX_ALLOCERROR); } nssSignedCrl = CERT_DecodeDERCrlWithFlags(NULL, derCrl, SEC_CRL_TYPE, CRL_DECODE_DONT_COPY_DER | CRL_DECODE_SKIP_ENTRIES); if (!nssSignedCrl) { PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED); } PKIX_CHECK( pkix_pl_CRL_CreateWithSignedCRL(nssSignedCrl, derCrl, NULL, &crl, plContext), PKIX_CRLCREATEWITHSIGNEDCRLFAILED); nssSignedCrl = NULL; derCrl = NULL; *pCrl = crl; cleanup: if (derCrl) { SECITEM_FreeItem(derCrl, PR_TRUE); } if (nssSignedCrl) { SEC_DestroyCrl(nssSignedCrl); } PKIX_RETURN(CRL); }
/* * 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_Date *date = NULL; SECItem nssTime = {siBuffer, NULL, 0}; SECStatus rv; 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; rv = DER_EncodeTimeChoice(NULL, &nssTime, date->nssTime); if (rv == SECFailure) { PKIX_ERROR(PKIX_DERENCODETIMECHOICEFAILED); } PKIX_CHECK(pkix_pl_Date_ToString_Helper (&nssTime, pString, plContext), PKIX_DATETOSTRINGHELPERFAILED); cleanup: if (nssTime.data) { SECITEM_FreeItem(&nssTime, PR_FALSE); } PKIX_RETURN(DATE); }
/* * FUNCTION: PKIX_List_GetItem (see comments in pkix_util.h) */ PKIX_Error * PKIX_List_GetItem( PKIX_List *list, PKIX_UInt32 index, PKIX_PL_Object **pItem, void *plContext) { PKIX_List *element = NULL; PKIX_ENTER(LIST, "PKIX_List_GetItem"); PKIX_NULLCHECK_TWO(list, pItem); if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), PKIX_LISTGETELEMENTFAILED); PKIX_INCREF(element->item); *pItem = element->item; cleanup: PKIX_RETURN(LIST); }
PKIX_Error * PKIX_PL_RWLock_Create( PKIX_PL_RWLock **pNewLock, void *plContext) { PKIX_PL_RWLock *rwLock = NULL; PKIX_ENTER(RWLOCK, "PKIX_PL_RWLock_Create"); PKIX_NULLCHECK_ONE(pNewLock); PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_RWLOCK_TYPE, sizeof (PKIX_PL_RWLock), (PKIX_PL_Object **)&rwLock, plContext), PKIX_ERRORALLOCATINGRWLOCK); PKIX_RWLOCK_DEBUG("\tCalling PR_NewRWLock)\n"); rwLock->lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "PKIX RWLock"); if (rwLock->lock == NULL) { PKIX_DECREF(rwLock); PKIX_ERROR(PKIX_OUTOFMEMORY); } rwLock->readCount = 0; rwLock->writeLocked = PKIX_FALSE; *pNewLock = rwLock; cleanup: PKIX_RETURN(RWLOCK); }
/* * FUNCTION: pkix_pl_CRL_GetVersion * DESCRIPTION: * * Retrieves the version of the CRL pointed to by "crl" and stores it at * "pVersion". The version number will either be 0 or 1 (corresponding to * v1 or v2, respectively). * * Version ::= INTEGER { v1(0), v2(1), v3(2) } * * PARAMETERS: * "crl" * Address of CRL whose version is to be stored. Must be non-NULL. * "pVersion" * Address where a version 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_GetVersion( PKIX_PL_CRL *crl, PKIX_UInt32 *pVersion, void *plContext) { PKIX_UInt32 myVersion; PKIX_ENTER(CRL, "pkix_pl_CRL_GetVersion"); PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pVersion); PKIX_NULLCHECK_ONE(crl->nssSignedCrl->crl.version.data); myVersion = *(crl->nssSignedCrl->crl.version.data); if (myVersion > 1) { PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1ORV2); } *pVersion = myVersion; cleanup: PKIX_RETURN(CRL); }
/* * FUNCTION: PKIX_List_IsEmpty (see comments in pkix_util.h) */ PKIX_Error * PKIX_List_IsEmpty( PKIX_List *list, PKIX_Boolean *pEmpty, void *plContext) { PKIX_UInt32 length; PKIX_ENTER(LIST, "PKIX_List_IsEmpty"); PKIX_NULLCHECK_TWO(list, pEmpty); if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } length = list->length; if (length == 0){ *pEmpty = PKIX_TRUE; } else { *pEmpty = PKIX_FALSE; } cleanup: PKIX_RETURN(LIST); }
PKIX_Error * PKIX_PL_MonitorLock_Create( PKIX_PL_MonitorLock **pNewLock, void *plContext) { PKIX_PL_MonitorLock *monitorLock = NULL; PKIX_ENTER(MONITORLOCK, "PKIX_PL_MonitorLock_Create"); PKIX_NULLCHECK_ONE(pNewLock); PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_MONITORLOCK_TYPE, sizeof (PKIX_PL_MonitorLock), (PKIX_PL_Object **)&monitorLock, plContext), PKIX_ERRORALLOCATINGMONITORLOCK); PKIX_MONITORLOCK_DEBUG("\tCalling PR_NewMonitor)\n"); monitorLock->lock = PR_NewMonitor(); if (monitorLock->lock == NULL) { PKIX_DECREF(monitorLock); PKIX_ERROR(PKIX_OUTOFMEMORY); } *pNewLock = monitorLock; cleanup: PKIX_RETURN(MONITORLOCK); }
/* * FUNCTION: PKIX_PL_OID_CreateBySECItem (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_OID_CreateBySECItem( SECItem *derOid, PKIX_PL_OID **pOID, void *plContext) { PKIX_PL_OID *oid = NULL; SECStatus rv; PKIX_ENTER(OID, "PKIX_PL_OID_CreateBySECItem"); PKIX_NULLCHECK_TWO(pOID, derOid); PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_OID_TYPE, sizeof (PKIX_PL_OID), (PKIX_PL_Object **)&oid, plContext), PKIX_COULDNOTCREATEOBJECT); rv = SECITEM_CopyItem(NULL, &oid->derOid, derOid); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OUTOFMEMORY); } *pOID = oid; oid = NULL; cleanup: PKIX_DECREF(oid); PKIX_RETURN(OID); }
/* * FUNCTION: PKIX_List_ReverseList (see comments in pkix_util.h) */ PKIX_Error * PKIX_List_ReverseList( PKIX_List *list, PKIX_List **pReversedList, void *plContext) { PKIX_List *reversedList = NULL; PKIX_PL_Object *item = NULL; PKIX_PL_Object *duplicateItem = NULL; PKIX_UInt32 length, i; PKIX_ENTER(LIST, "pkix_List_ReverseList"); PKIX_NULLCHECK_TWO(list, pReversedList); if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } length = list->length; /* Create a new list object */ PKIX_CHECK(PKIX_List_Create(&reversedList, plContext), PKIX_LISTCREATEINTERNALFAILED); /* * Starting with the last item and traversing backwards (from * the original list), append each item to the reversed list */ for (i = 1; i <= length; i++){ PKIX_CHECK(PKIX_List_GetItem (list, (length - i), &item, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(PKIX_PL_Object_Duplicate (item, &duplicateItem, plContext), PKIX_LISTDUPLICATEFAILED); PKIX_CHECK(PKIX_List_AppendItem (reversedList, duplicateItem, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(item); PKIX_DECREF(duplicateItem); } *pReversedList = reversedList; cleanup: PKIX_DECREF(item); PKIX_DECREF(duplicateItem); if (PKIX_ERROR_RECEIVED){ PKIX_DECREF(reversedList); } PKIX_RETURN(LIST); }
/* * FUNCTION: PKIX_Error_Create (see comments in pkix_util.h) */ PKIX_Error * PKIX_Error_Create( PKIX_ERRORCLASS errClass, PKIX_Error *cause, PKIX_PL_Object *info, PKIX_ERRORCODE errCode, PKIX_Error **pError, void *plContext) { PKIX_Error *tempCause = NULL; PKIX_Error *error = NULL; PKIX_ENTER(ERROR, "PKIX_Error_Create"); PKIX_NULLCHECK_ONE(pError); /* * when called here, if PKIX_PL_Object_Alloc returns an error, * it must be a PKIX_ALLOC_ERROR */ pkixErrorResult = PKIX_PL_Object_Alloc (PKIX_ERROR_TYPE, ((PKIX_UInt32)(sizeof (PKIX_Error))), (PKIX_PL_Object **)&error, plContext); if (pkixErrorResult) return (pkixErrorResult); error->errClass = errClass; /* Ensure we don't have a loop. Follow causes until NULL */ for (tempCause = cause; tempCause != NULL; tempCause = tempCause->cause) { /* If we detect a loop, throw a new error */ if (tempCause == error) { PKIX_ERROR(PKIX_LOOPOFERRORCAUSEDETECTED); } } PKIX_INCREF(cause); error->cause = cause; PKIX_INCREF(info); error->info = info; error->errCode = errCode; error->plErr = PKIX_PLErrorIndex[error->errCode]; *pError = error; error = NULL; cleanup: /* PKIX-XXX Fix for leak during error creation */ PKIX_DECREF(error); PKIX_RETURN(ERROR); }
/* * FUNCTION: pkix_pl_Date_ToString_Helper * DESCRIPTION: * * Helper function that creates a string representation of the SECItem pointed * to by "nssTime" (which represents a date) and stores it at "pString". * * PARAMETERS * "nssTime" * Address of SECItem 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 Date 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_Date_ToString_Helper( SECItem *nssTime, PKIX_PL_String **pString, void *plContext) { char *asciiDate = NULL; PKIX_ENTER(DATE, "pkix_pl_Date_ToString_Helper"); PKIX_NULLCHECK_TWO(nssTime, pString); switch (nssTime->type) { case siUTCTime: PKIX_PL_NSSCALLRV (DATE, asciiDate, DER_UTCDayToAscii, (nssTime)); if (!asciiDate){ PKIX_ERROR(PKIX_DERUTCTIMETOASCIIFAILED); } break; case siGeneralizedTime: /* * we don't currently have any way to create GeneralizedTime. * this code is only here so that it will be in place when * we do have the capability to create GeneralizedTime. */ PKIX_PL_NSSCALLRV (DATE, asciiDate, DER_GeneralizedDayToAscii, (nssTime)); if (!asciiDate){ PKIX_ERROR(PKIX_DERGENERALIZEDDAYTOASCIIFAILED); } break; default: PKIX_ERROR(PKIX_UNRECOGNIZEDTIMETYPE); } PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, asciiDate, 0, pString, plContext), PKIX_STRINGCREATEFAILED); cleanup: PR_Free(asciiDate); PKIX_RETURN(DATE); }
/* * 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); }
/* * This function is based on CERT_DecodeCertPackage from lib/pkcs7/certread.c * read an old style ascii or binary certificate chain */ PKIX_Error * pkix_pl_HttpCertStore_DecodeCertPackage (const char *certbuf, int certlen, CERTImportCertificateFunc f, void *arg, void *plContext) { PRStatus status; SECStatus rv; PKIX_ENTER (HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStore_DecodeCertPackage"); PKIX_NULLCHECK_TWO(certbuf, f); status = PR_CallOnce(&pkix_decodeFunc.once, pkix_getDecodeFunction); if (status != PR_SUCCESS) { PKIX_ERROR(PKIX_CANTLOADLIBSMIME); } /* paranoia, shouldn't happen if status == PR_SUCCESS); */ if (!pkix_decodeFunc.func) { PKIX_ERROR(PKIX_CANTLOADLIBSMIME); } rv = (*pkix_decodeFunc.func)((char*)certbuf, certlen, f, arg); if (rv != SECSuccess) { PKIX_ERROR (PKIX_SECREADPKCS7CERTSFAILED); } cleanup: PKIX_RETURN(HTTPCERTSTORECONTEXT); }
PKIX_Error* PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl, SECItem *derCrl, void *plContext) { PKIX_ENTER(CRL, "PKIX_PL_CRL_AquireDerCrl"); if (crl->adoptedDerCrl) { PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER); } crl->adoptedDerCrl = derCrl; cleanup: PKIX_RETURN(CRL); }
/* * FUNCTION: PKIX_List_SetItem (see comments in pkix_util.h) */ PKIX_Error * PKIX_List_SetItem( PKIX_List *list, PKIX_UInt32 index, PKIX_PL_Object *item, void *plContext) { PKIX_List *element; PKIX_ENTER(LIST, "PKIX_List_SetItem"); PKIX_NULLCHECK_ONE(list); if (list->immutable){ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); } if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), PKIX_LISTGETELEMENTFAILED); /* DecRef old contents */ PKIX_DECREF(element->item); /* Set New Contents */ PKIX_INCREF(item); element->item = item; PKIX_CHECK(PKIX_PL_Object_InvalidateCache ((PKIX_PL_Object *)list, plContext), PKIX_OBJECTINVALIDATECACHEFAILED); cleanup: PKIX_RETURN(LIST); }
/* * FUNCTION: PKIX_TrustAnchor_CreateWithNameKeyPair * (see comments in pkix_params.h) */ PKIX_Error * PKIX_TrustAnchor_CreateWithNameKeyPair( PKIX_PL_X500Name *name, PKIX_PL_PublicKey *pubKey, PKIX_PL_CertNameConstraints *nameConstraints, PKIX_TrustAnchor **pAnchor, void *plContext) { PKIX_TrustAnchor *anchor = NULL; PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithNameKeyPair"); #ifndef BUILD_LIBPKIX_TESTS /* Nss creates trust anchors by using PKIX_TrustAnchor_CreateWithCert * function as the complete trusted cert structure, and not only cert * public key, is required for chain building and validation processes. * Restricting this function for been used only in libpkix unit * tests. */ PKIX_ERROR(PKIX_FUNCTIONMUSTNOTBEUSED); #endif PKIX_NULLCHECK_THREE(name, pubKey, pAnchor); PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_TRUSTANCHOR_TYPE, sizeof (PKIX_TrustAnchor), (PKIX_PL_Object **)&anchor, plContext), PKIX_COULDNOTCREATETRUSTANCHOROBJECT); /* initialize fields */ anchor->trustedCert = NULL; PKIX_INCREF(name); anchor->caName = name; PKIX_INCREF(pubKey); anchor->caPubKey = pubKey; PKIX_INCREF(nameConstraints); anchor->nameConstraints = nameConstraints; *pAnchor = anchor; anchor = NULL; cleanup: PKIX_DECREF(anchor); PKIX_RETURN(TRUSTANCHOR); }
/* * FUNCTION: pkix_List_Hashcode * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_List_Hashcode( PKIX_PL_Object *object, PKIX_UInt32 *pHashcode, void *plContext) { PKIX_List *list = NULL; PKIX_PL_Object *element = NULL; PKIX_UInt32 hash = 0; PKIX_UInt32 tempHash = 0; PKIX_UInt32 length, i; PKIX_ENTER(LIST, "pkix_List_Hashcode"); PKIX_NULLCHECK_TWO(object, pHashcode); PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), PKIX_OBJECTNOTLIST); list = (PKIX_List *)object; if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } length = list->length; for (i = 0; i < length; i++){ PKIX_CHECK(PKIX_List_GetItem(list, i, &element, plContext), PKIX_LISTGETITEMFAILED); if (!element){ tempHash = 100; } else { PKIX_CHECK(PKIX_PL_Object_Hashcode (element, &tempHash, plContext), PKIX_LISTHASHCODEFAILED); } hash = 31 * hash + tempHash; PKIX_DECREF(element); } *pHashcode = hash; cleanup: PKIX_DECREF(element); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_pl_HttpCertStore_CreateRequestSession * DESCRIPTION: * * This function takes elements from the HttpCertStoreContext pointed to by * "context" (path, client, and serverSession) and creates a RequestSession. * See the HTTPClient API described in ocspt.h for further details. * * PARAMETERS: * "context" * The address of the HttpCertStoreContext. 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 HttpCertStore 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_HttpCertStore_CreateRequestSession( PKIX_PL_HttpCertStoreContext *context, void *plContext) { const SEC_HttpClientFcnV1 *hcv1 = NULL; SECStatus rv = SECFailure; PKIX_ENTER (HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStore_CreateRequestSession"); PKIX_NULLCHECK_TWO(context, context->serverSession); if (context->client->version != 1) { PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); } hcv1 = &(context->client->fcnTable.ftable1); if (context->requestSession != NULL) { (*hcv1->freeFcn)(context->requestSession); context->requestSession = 0; } rv = (*hcv1->createFcn)(context->serverSession, "http", context->path, "GET", PR_SecondsToInterval( ((PKIX_PL_NssContext*)plContext)->timeoutSeconds), &(context->requestSession)); if (rv != SECSuccess) { PKIX_ERROR(PKIX_HTTPSERVERERROR); } cleanup: PKIX_RETURN(HTTPCERTSTORECONTEXT); }
/* * FUNCTION: pkix_pl_LdapCertStore_DecodeCrossCertPair * DESCRIPTION: * * This function decodes a DER-encoded CrossCertPair pointed to by * "responseList" and extracts and decodes the Certificates in that pair, * adding the resulting Certs, if the decoding was successful, to the List * (possibly empty) pointed to by "certList". If none of the objects * can be decoded into a Cert, the List is returned unchanged. * * PARAMETERS: * "derCCPItem" * The address of the SECItem containing the DER representation of the * CrossCertPair. Must be non-NULL. * "certList" * The address of the List to which the decoded Certs are added. May be * empty, but 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 CertStore 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_LdapCertStore_DecodeCrossCertPair( SECItem *derCCPItem, PKIX_List *certList, void *plContext) { LDAPCertPair certPair = {{ siBuffer, NULL, 0 }, { siBuffer, NULL, 0 }}; SECStatus rv = SECFailure; PRArenaPool *tempArena = NULL; PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_DecodeCrossCertPair"); PKIX_NULLCHECK_TWO(derCCPItem, certList); tempArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!tempArena) { PKIX_ERROR(PKIX_OUTOFMEMORY); } rv = SEC_ASN1DecodeItem(tempArena, &certPair, PKIX_PL_LDAPCrossCertPairTemplate, derCCPItem); if (rv != SECSuccess) { goto cleanup; } if (certPair.forward.data != NULL) { PKIX_CHECK( pkix_pl_Cert_CreateToList(&certPair.forward, certList, plContext), PKIX_CERTCREATETOLISTFAILED); } if (certPair.reverse.data != NULL) { PKIX_CHECK( pkix_pl_Cert_CreateToList(&certPair.reverse, certList, plContext), PKIX_CERTCREATETOLISTFAILED); } cleanup: if (tempArena) { PORT_FreeArena(tempArena, PR_FALSE); } PKIX_RETURN(CERTSTORE); }
/* * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL * DESCRIPTION: * * Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl" * and stores it at "pCRL". If the decoding of the CERTSignedCrl fails, * a PKIX_Error is returned. * * PARAMETERS: * "nssSignedCrl" * Address of CERTSignedCrl. Must be non-NULL. * "adoptedDerCrl" * SECItem ponter that if not NULL is indicating that memory used * for der should be adopted by crl that is about to be created. * "pCRL" * 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. */ PKIX_Error * pkix_pl_CRL_CreateWithSignedCRL( CERTSignedCrl *nssSignedCrl, SECItem *adoptedDerCrl, SECItem *derGenName, PKIX_PL_CRL **pCrl, void *plContext) { PKIX_PL_CRL *crl = NULL; PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL"); PKIX_NULLCHECK_ONE(pCrl); /* create a PKIX_PL_CRL object */ PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_CRL_TYPE, sizeof (PKIX_PL_CRL), (PKIX_PL_Object **)&crl, plContext), PKIX_COULDNOTCREATECRLOBJECT); /* populate the nssSignedCrl field */ crl->nssSignedCrl = nssSignedCrl; crl->adoptedDerCrl = adoptedDerCrl; crl->issuer = NULL; crl->signatureAlgId = NULL; crl->crlNumber = NULL; crl->crlNumberAbsent = PKIX_FALSE; crl->crlEntryList = NULL; crl->critExtOids = NULL; if (derGenName) { crl->derGenName = SECITEM_DupItem(derGenName); if (!crl->derGenName) { PKIX_ERROR(PKIX_ALLOCERROR); } } *pCrl = crl; cleanup: if (PKIX_ERROR_RECEIVED){ PKIX_DECREF(crl); } PKIX_RETURN(CRL); }
/* * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL * DESCRIPTION: * * Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl" * and stores it at "pCRL". If the decoding of the CERTSignedCrl fails, * a PKIX_Error is returned. * * PARAMETERS: * "nssSignedCrl" * Address of CERTSignedCrl. Must be non-NULL. * "pCRL" * 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. */ PKIX_Error * pkix_pl_CRL_CreateWithSignedCRL( CERTSignedCrl *nssSignedCrl, PKIX_PL_CRL **pCrl, void *plContext) { SECStatus status; PKIX_PL_CRL *crl = NULL; PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL"); PKIX_NULLCHECK_TWO(nssSignedCrl, pCrl); /* create a PKIX_PL_CRL object */ PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_CRL_TYPE, sizeof (PKIX_PL_CRL), (PKIX_PL_Object **)&crl, plContext), PKIX_COULDNOTCREATECRLOBJECT); /* populate the nssSignedCrl field */ crl->nssSignedCrl = nssSignedCrl; PKIX_CRL_DEBUG("\t\tCalling CERT_CompleteCRLDecodeEntries\n"); status = CERT_CompleteCRLDecodeEntries(crl->nssSignedCrl); if (status != SECSuccess) { PKIX_ERROR(PKIX_CERTCOMPLETECRLDECODEDENTRIESFAILED); } crl->issuer = NULL; crl->signatureAlgId = NULL; crl->crlNumber = NULL; crl->crlNumberAbsent = PKIX_FALSE; crl->crlEntryList = NULL; crl->critExtOids = NULL; *pCrl = crl; cleanup: if (PKIX_ERROR_RECEIVED) { PKIX_DECREF(crl); } PKIX_RETURN(CRL); }
/* * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds * (see comments in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_Date_Create_CurrentOffBySeconds( PKIX_Int32 secondsOffset, PKIX_PL_Date **pDate, void *plContext) { PKIX_PL_Date *date = NULL; SECItem nssTime; SECStatus rv; PRTime time; PKIX_ENTER(DATE, "PKIX_PL_Date_Create_CurrentOffBySeconds"); PKIX_NULLCHECK_ONE(pDate); PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n"); time = PR_Now(); time += (secondsOffset * PR_USEC_PER_SEC); PKIX_DATE_DEBUG("\t\tCalling DER_TimeToUTCTime).\n"); rv = DER_TimeToUTCTime(&nssTime, time); if (rv != SECSuccess){ PKIX_ERROR(PKIX_DERTIMETOUTCTIMEFAILED); } /* 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 = nssTime; *pDate = date; cleanup: if (PKIX_ERROR_RECEIVED){ PR_Free(nssTime.data); } PKIX_RETURN(DATE); }
/* * 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); }