| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| /* |
| * pkix_pl_date.c |
| * |
| * Date Object Definitions |
| * |
| */ |
| |
| #include "pkix_pl_date.h" |
| |
| /* --Private-Date-Functions------------------------------------- */ |
| /* |
| * FUNCTION: pkix_pl_Date_GetPRTime |
| * DESCRIPTION: |
| * |
| * Translates into a PRTime the Date embodied by the Date object pointed to |
| * by "date", and stores it at "pPRTime". |
| * |
| * PARAMETERS |
| * "date" |
| * Address of Date whose PRTime representation is desired. Must be |
| * non-NULL. |
| * "pPRTime" |
| * Address where PRTime value 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_GetPRTime( |
| PKIX_PL_Date *date, |
| PRTime *pPRTime, |
| void *plContext) |
| { |
| PKIX_ENTER(DATE, "PKIX_PL_Date_GetPRTime"); |
| PKIX_NULLCHECK_TWO(date, pPRTime); |
| |
| *pPRTime = date->nssTime; |
| |
| PKIX_RETURN(DATE); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_Date_CreateFromPRTime |
| * DESCRIPTION: |
| * |
| * Creates a new Date from the PRTime whose value is "prtime", and stores the |
| * result at "pDate". |
| * |
| * PARAMETERS |
| * "prtime" |
| * The PRTime value to be embodied in the new Date object. |
| * "pDate" |
| * 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_CreateFromPRTime( |
| PRTime prtime, |
| PKIX_PL_Date **pDate, |
| void *plContext) |
| { |
| PKIX_PL_Date *date = NULL; |
| |
| PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime"); |
| PKIX_NULLCHECK_ONE(pDate); |
| |
| /* 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 = prtime; |
| *pDate = date; |
| cleanup: |
| PKIX_RETURN(DATE); |
| } |
| |
| /* |
| * 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_Destroy |
| * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_pl_Date_Destroy( |
| PKIX_PL_Object *object, |
| void *plContext) |
| { |
| PKIX_ENTER(DATE, "pkix_pl_Date_Destroy"); |
| PKIX_NULLCHECK_ONE(object); |
| |
| PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext), |
| PKIX_OBJECTNOTDATE); |
| cleanup: |
| PKIX_RETURN(DATE); |
| } |
| |
| /* |
| * 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_pl_Date_Hashcode |
| * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_pl_Date_Hashcode( |
| PKIX_PL_Object *object, |
| PKIX_UInt32 *pHashcode, |
| void *plContext) |
| { |
| PKIX_PL_Date *date = NULL; |
| PKIX_UInt32 dateHash; |
| |
| PKIX_ENTER(DATE, "pkix_pl_Date_Hashcode"); |
| PKIX_NULLCHECK_TWO(object, pHashcode); |
| |
| PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext), |
| PKIX_OBJECTNOTDATE); |
| |
| date = (PKIX_PL_Date *)object; |
| |
| PKIX_CHECK(pkix_hash |
| ((const unsigned char *)&date->nssTime, |
| sizeof(date->nssTime), |
| &dateHash, |
| plContext), |
| PKIX_HASHFAILED); |
| |
| *pHashcode = dateHash; |
| |
| cleanup: |
| |
| PKIX_RETURN(DATE); |
| |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_Date_Comparator |
| * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_pl_Date_Comparator( |
| PKIX_PL_Object *firstObject, |
| PKIX_PL_Object *secondObject, |
| PKIX_Int32 *pResult, |
| void *plContext) |
| { |
| PRTime firstTime; |
| PRTime secondTime; |
| SECComparison cmpResult; |
| |
| PKIX_ENTER(DATE, "pkix_pl_Date_Comparator"); |
| PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); |
| |
| PKIX_CHECK(pkix_CheckTypes |
| (firstObject, secondObject, PKIX_DATE_TYPE, plContext), |
| PKIX_ARGUMENTSNOTDATES); |
| |
| firstTime = ((PKIX_PL_Date *)firstObject)->nssTime; |
| secondTime = ((PKIX_PL_Date *)secondObject)->nssTime; |
| |
| if (firstTime == secondTime) |
| cmpResult = SECEqual; |
| else if (firstTime < secondTime) |
| cmpResult = SECLessThan; |
| else |
| cmpResult = SECGreaterThan; |
| |
| *pResult = cmpResult; |
| |
| cleanup: |
| |
| PKIX_RETURN(DATE); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_Date_Equals |
| * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_pl_Date_Equals( |
| PKIX_PL_Object *firstObject, |
| PKIX_PL_Object *secondObject, |
| PKIX_Boolean *pResult, |
| void *plContext) |
| { |
| PKIX_ENTER(DATE, "pkix_pl_Date_Equals"); |
| PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); |
| |
| /* test that firstObject is a Date */ |
| PKIX_CHECK(pkix_CheckType(firstObject, PKIX_DATE_TYPE, plContext), |
| PKIX_FIRSTOBJECTNOTDATE); |
| |
| /* |
| * Since we know firstObject is a Date, if both references are |
| * identical, they must be equal |
| */ |
| if (firstObject == secondObject){ |
| *pResult = PKIX_TRUE; |
| goto cleanup; |
| } |
| |
| *pResult = PKIX_FALSE; |
| pkixErrorResult = |
| pkix_pl_Date_Comparator(firstObject, secondObject, |
| pResult, plContext); |
| if (pkixErrorResult) { |
| PKIX_DECREF(pkixErrorResult); |
| } |
| |
| cleanup: |
| |
| PKIX_RETURN(DATE); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_Date_RegisterSelf |
| * DESCRIPTION: |
| * Registers PKIX_DATE_TYPE and its related functions with systemClasses[] |
| * THREAD SAFETY: |
| * Not Thread Safe - for performance and complexity reasons |
| * |
| * Since this function is only called by PKIX_PL_Initialize, which should |
| * only be called once, it is acceptable that this function is not |
| * thread-safe. |
| */ |
| PKIX_Error * |
| pkix_pl_Date_RegisterSelf(void *plContext) |
| { |
| extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; |
| pkix_ClassTable_Entry* entry = &systemClasses[PKIX_DATE_TYPE]; |
| |
| PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_RegisterSelf"); |
| |
| entry->description = "Date"; |
| entry->typeObjectSize = sizeof(PKIX_PL_Date); |
| entry->destructor = pkix_pl_Date_Destroy; |
| entry->equalsFunction = pkix_pl_Date_Equals; |
| entry->hashcodeFunction = pkix_pl_Date_Hashcode; |
| entry->toStringFunction = pkix_pl_Date_ToString; |
| entry->comparator = pkix_pl_Date_Comparator; |
| entry->duplicateFunction = pkix_duplicateImmutable; |
| |
| PKIX_RETURN(DATE); |
| } |
| |
| /* --Public-Functions------------------------------------------------------- */ |
| |
| /* |
| * 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_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; |
| PRTime time; |
| |
| PKIX_ENTER(DATE, "PKIX_PL_Date_Create_CurrentOffBySeconds"); |
| PKIX_NULLCHECK_ONE(pDate); |
| |
| time = PR_Now() + PR_SecondsToInterval(secondsOffset); |
| /* 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_RETURN(DATE); |
| } |
| |
| PKIX_Error * |
| PKIX_PL_Date_CreateFromPRTime( |
| PRTime prtime, |
| PKIX_PL_Date **pDate, |
| void *plContext) |
| { |
| PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime"); |
| PKIX_CHECK( |
| pkix_pl_Date_CreateFromPRTime(prtime, pDate, plContext), |
| PKIX_DATECREATEFROMPRTIMEFAILED); |
| |
| cleanup: |
| PKIX_RETURN(DATE); |
| } |