diff options
Diffstat (limited to 'lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c')
-rw-r--r-- | lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c | 466 |
1 files changed, 466 insertions, 0 deletions
diff --git a/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c b/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c new file mode 100644 index 000000000..4b5016bd0 --- /dev/null +++ b/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c @@ -0,0 +1,466 @@ +/* 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); +} |