tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_pl_date.c (13629B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * pkix_pl_date.c
      6 *
      7 * Date Object Definitions
      8 *
      9 */
     10 
     11 #include "pkix_pl_date.h"
     12 
     13 /* --Private-Date-Functions------------------------------------- */
     14 /*
     15 * FUNCTION: pkix_pl_Date_GetPRTime
     16 * DESCRIPTION:
     17 *
     18 *  Translates into a PRTime the Date embodied by the Date object pointed to
     19 *  by "date", and stores it at "pPRTime".
     20 *
     21 * PARAMETERS
     22 *  "date"
     23 *      Address of Date whose PRTime representation is desired. Must be
     24 *      non-NULL.
     25 *  "pPRTime"
     26 *      Address where PRTime value will be stored. Must be non-NULL.
     27 *  "plContext" - Platform-specific context pointer.
     28 * THREAD SAFETY:
     29 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     30 * RETURNS:
     31 *  Returns NULL if the function succeeds.
     32 *  Returns a Date Error if the function fails in a non-fatal way.
     33 *  Returns a Fatal Error if the function fails in an unrecoverable way.
     34 */
     35 PKIX_Error *
     36 pkix_pl_Date_GetPRTime(
     37        PKIX_PL_Date *date,
     38        PRTime *pPRTime,
     39        void *plContext)
     40 {
     41        PKIX_ENTER(DATE, "PKIX_PL_Date_GetPRTime");
     42        PKIX_NULLCHECK_TWO(date, pPRTime);
     43 
     44        *pPRTime = date->nssTime;
     45 
     46        PKIX_RETURN(DATE);
     47 }
     48 
     49 /*
     50 * FUNCTION: pkix_pl_Date_CreateFromPRTime
     51 * DESCRIPTION:
     52 *
     53 *  Creates a new Date from the PRTime whose value is "prtime", and stores the
     54 *  result at "pDate".
     55 *
     56 * PARAMETERS
     57 *  "prtime"
     58 *      The PRTime value to be embodied in the new Date object.
     59 *  "pDate"
     60 *      Address where object pointer will be stored. Must be non-NULL.
     61 *  "plContext" - Platform-specific context pointer.
     62 * THREAD SAFETY:
     63 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     64 * RETURNS:
     65 *  Returns NULL if the function succeeds.
     66 *  Returns a Date Error if the function fails in a non-fatal way.
     67 *  Returns a Fatal Error if the function fails in an unrecoverable way.
     68 */
     69 PKIX_Error *
     70 pkix_pl_Date_CreateFromPRTime(
     71        PRTime prtime,
     72        PKIX_PL_Date **pDate,
     73        void *plContext)
     74 {
     75        PKIX_PL_Date *date = NULL;
     76 
     77        PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime");
     78        PKIX_NULLCHECK_ONE(pDate);
     79 
     80        /* create a PKIX_PL_Date object */
     81        PKIX_CHECK(PKIX_PL_Object_Alloc
     82                    (PKIX_DATE_TYPE,
     83                    sizeof (PKIX_PL_Date),
     84                    (PKIX_PL_Object **)&date,
     85                    plContext),
     86                    PKIX_COULDNOTCREATEOBJECT);
     87        /* populate the nssTime field */
     88        date->nssTime = prtime;
     89        *pDate = date;
     90 cleanup:
     91        PKIX_RETURN(DATE);
     92 }
     93 
     94 /*
     95 * FUNCTION: pkix_pl_Date_ToString_Helper
     96 * DESCRIPTION:
     97 *
     98 *  Helper function that creates a string representation of the SECItem pointed
     99 *  to by "nssTime" (which represents a date) and stores it at "pString".
    100 *
    101 * PARAMETERS
    102 *  "nssTime"
    103 *      Address of SECItem whose string representation is desired.
    104 *      Must be non-NULL.
    105 *  "pString"
    106 *      Address where object pointer will be stored. Must be non-NULL.
    107 *  "plContext" - Platform-specific context pointer.
    108 * THREAD SAFETY:
    109 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    110 * RETURNS:
    111 *  Returns NULL if the function succeeds.
    112 *  Returns a Date Error if the function fails in a non-fatal way.
    113 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    114 */
    115 PKIX_Error *
    116 pkix_pl_Date_ToString_Helper(
    117        SECItem *nssTime,
    118        PKIX_PL_String **pString,
    119        void *plContext)
    120 {
    121        char *asciiDate = NULL;
    122 
    123        PKIX_ENTER(DATE, "pkix_pl_Date_ToString_Helper");
    124        PKIX_NULLCHECK_TWO(nssTime, pString);
    125 
    126        switch (nssTime->type) {
    127        case siUTCTime:
    128                PKIX_PL_NSSCALLRV
    129                        (DATE, asciiDate, DER_UTCDayToAscii, (nssTime));
    130                if (!asciiDate){
    131                        PKIX_ERROR(PKIX_DERUTCTIMETOASCIIFAILED);
    132                }
    133                break;
    134        case siGeneralizedTime:
    135                /*
    136                 * we don't currently have any way to create GeneralizedTime.
    137                 * this code is only here so that it will be in place when
    138                 * we do have the capability to create GeneralizedTime.
    139                 */
    140                PKIX_PL_NSSCALLRV
    141                        (DATE, asciiDate, DER_GeneralizedDayToAscii, (nssTime));
    142                if (!asciiDate){
    143                        PKIX_ERROR(PKIX_DERGENERALIZEDDAYTOASCIIFAILED);
    144                }
    145                break;
    146        default:
    147                PKIX_ERROR(PKIX_UNRECOGNIZEDTIMETYPE);
    148        }
    149 
    150        PKIX_CHECK(PKIX_PL_String_Create
    151                    (PKIX_ESCASCII, asciiDate, 0, pString, plContext),
    152                    PKIX_STRINGCREATEFAILED);
    153 
    154 cleanup:
    155        PR_Free(asciiDate);
    156 
    157        PKIX_RETURN(DATE);
    158 }
    159 
    160 
    161 /*
    162 * FUNCTION: pkix_pl_Date_Destroy
    163 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
    164 */
    165 static PKIX_Error *
    166 pkix_pl_Date_Destroy(
    167        PKIX_PL_Object *object,
    168        void *plContext)
    169 {
    170        PKIX_ENTER(DATE, "pkix_pl_Date_Destroy");
    171        PKIX_NULLCHECK_ONE(object);
    172 
    173        PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
    174                    PKIX_OBJECTNOTDATE);
    175 cleanup:
    176        PKIX_RETURN(DATE);
    177 }
    178 
    179 /*
    180 * FUNCTION: pkix_pl_Date_ToString
    181 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
    182 */
    183 static PKIX_Error *
    184 pkix_pl_Date_ToString(
    185        PKIX_PL_Object *object,
    186        PKIX_PL_String **pString,
    187        void *plContext)
    188 {
    189        PKIX_PL_Date *date = NULL;
    190        SECItem nssTime = {siBuffer, NULL, 0};
    191        SECStatus rv;
    192 
    193        PKIX_ENTER(DATE, "pkix_pl_Date_toString");
    194        PKIX_NULLCHECK_TWO(object, pString);
    195 
    196        PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
    197                    PKIX_OBJECTNOTDATE);
    198 
    199        date = (PKIX_PL_Date *)object;
    200        rv = DER_EncodeTimeChoice(NULL, &nssTime, date->nssTime);
    201        if (rv == SECFailure) {
    202            PKIX_ERROR(PKIX_DERENCODETIMECHOICEFAILED);
    203        }
    204        PKIX_CHECK(pkix_pl_Date_ToString_Helper
    205                    (&nssTime, pString, plContext),
    206                    PKIX_DATETOSTRINGHELPERFAILED);
    207 cleanup:
    208        if (nssTime.data) {
    209            SECITEM_FreeItem(&nssTime, PR_FALSE);
    210        }
    211 
    212        PKIX_RETURN(DATE);
    213 }
    214 
    215 /*
    216 * FUNCTION: pkix_pl_Date_Hashcode
    217 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
    218 */
    219 static PKIX_Error *
    220 pkix_pl_Date_Hashcode(
    221        PKIX_PL_Object *object,
    222        PKIX_UInt32 *pHashcode,
    223        void *plContext)
    224 {
    225        PKIX_PL_Date *date = NULL;
    226        PKIX_UInt32 dateHash;
    227 
    228        PKIX_ENTER(DATE, "pkix_pl_Date_Hashcode");
    229        PKIX_NULLCHECK_TWO(object, pHashcode);
    230 
    231        PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
    232                    PKIX_OBJECTNOTDATE);
    233 
    234        date = (PKIX_PL_Date *)object;
    235 
    236        PKIX_CHECK(pkix_hash
    237                ((const unsigned char *)&date->nssTime,
    238                sizeof(date->nssTime),
    239                &dateHash,
    240                plContext),
    241                PKIX_HASHFAILED);
    242 
    243        *pHashcode = dateHash;
    244 
    245 cleanup:
    246 
    247        PKIX_RETURN(DATE);
    248 
    249 }
    250 
    251 /*
    252 * FUNCTION: pkix_pl_Date_Comparator
    253 * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
    254 */
    255 static PKIX_Error *
    256 pkix_pl_Date_Comparator(
    257        PKIX_PL_Object *firstObject,
    258        PKIX_PL_Object *secondObject,
    259        PKIX_Int32 *pResult,
    260        void *plContext)
    261 {
    262        PRTime firstTime;
    263        PRTime secondTime;
    264        SECComparison cmpResult;
    265 
    266        PKIX_ENTER(DATE, "pkix_pl_Date_Comparator");
    267        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
    268 
    269        PKIX_CHECK(pkix_CheckTypes
    270                    (firstObject, secondObject, PKIX_DATE_TYPE, plContext),
    271                    PKIX_ARGUMENTSNOTDATES);
    272 
    273        firstTime = ((PKIX_PL_Date *)firstObject)->nssTime;
    274        secondTime = ((PKIX_PL_Date *)secondObject)->nssTime;
    275 
    276        if (firstTime == secondTime)
    277            cmpResult = SECEqual;
    278        else if (firstTime < secondTime)
    279            cmpResult = SECLessThan;
    280        else
    281            cmpResult = SECGreaterThan;
    282 
    283        *pResult = cmpResult;
    284 
    285 cleanup:
    286 
    287        PKIX_RETURN(DATE);
    288 }
    289 
    290 /*
    291 * FUNCTION: pkix_pl_Date_Equals
    292 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
    293 */
    294 static PKIX_Error *
    295 pkix_pl_Date_Equals(
    296        PKIX_PL_Object *firstObject,
    297        PKIX_PL_Object *secondObject,
    298        PKIX_Boolean *pResult,
    299        void *plContext)
    300 {
    301        PKIX_ENTER(DATE, "pkix_pl_Date_Equals");
    302        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
    303 
    304        /* test that firstObject is a Date */
    305        PKIX_CHECK(pkix_CheckType(firstObject, PKIX_DATE_TYPE, plContext),
    306                PKIX_FIRSTOBJECTNOTDATE);
    307 
    308        /*
    309         * Since we know firstObject is a Date, if both references are
    310         * identical, they must be equal
    311         */
    312        if (firstObject == secondObject){
    313                *pResult = PKIX_TRUE;
    314                goto cleanup;
    315        }
    316 
    317        *pResult = PKIX_FALSE;
    318        pkixErrorResult =
    319            pkix_pl_Date_Comparator(firstObject, secondObject,
    320                                    pResult, plContext);
    321        if (pkixErrorResult) {
    322            PKIX_DECREF(pkixErrorResult);
    323        }
    324            
    325 cleanup:
    326 
    327        PKIX_RETURN(DATE);
    328 }
    329 
    330 /*
    331 * FUNCTION: pkix_pl_Date_RegisterSelf
    332 * DESCRIPTION:
    333 *  Registers PKIX_DATE_TYPE and its related functions with systemClasses[]
    334 * THREAD SAFETY:
    335 *  Not Thread Safe - for performance and complexity reasons
    336 *
    337 *  Since this function is only called by PKIX_PL_Initialize, which should
    338 *  only be called once, it is acceptable that this function is not
    339 *  thread-safe.
    340 */
    341 PKIX_Error *
    342 pkix_pl_Date_RegisterSelf(void *plContext)
    343 {
    344        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
    345        pkix_ClassTable_Entry* entry = &systemClasses[PKIX_DATE_TYPE];
    346 
    347        PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_RegisterSelf");
    348 
    349        entry->description = "Date";
    350        entry->typeObjectSize = sizeof(PKIX_PL_Date);
    351        entry->destructor = pkix_pl_Date_Destroy;
    352        entry->equalsFunction = pkix_pl_Date_Equals;
    353        entry->hashcodeFunction = pkix_pl_Date_Hashcode;
    354        entry->toStringFunction = pkix_pl_Date_ToString;
    355        entry->comparator = pkix_pl_Date_Comparator;
    356        entry->duplicateFunction = pkix_duplicateImmutable;
    357 
    358        PKIX_RETURN(DATE);
    359 }
    360 
    361 /* --Public-Functions------------------------------------------------------- */
    362 
    363 /*
    364 * FUNCTION: PKIX_PL_Date_Create_UTCTime (see comments in pkix_pl_pki.h)
    365 */
    366 PKIX_Error *
    367 PKIX_PL_Date_Create_UTCTime(
    368        PKIX_PL_String *stringRep,
    369        PKIX_PL_Date **pDate,
    370        void *plContext)
    371 {
    372        PKIX_PL_Date *date = NULL;
    373        char *asciiString = NULL;
    374        PKIX_UInt32 escAsciiLength;
    375        SECStatus rv;
    376        PRTime time;
    377 
    378        PKIX_ENTER(DATE, "PKIX_PL_Date_Create_UTCTime");
    379        PKIX_NULLCHECK_ONE(pDate);
    380 
    381        if (stringRep == NULL){
    382                PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n");
    383                time = PR_Now();
    384        } else {
    385                /* convert the input PKIX_PL_String to PKIX_ESCASCII */
    386                PKIX_CHECK(PKIX_PL_String_GetEncoded
    387                            (stringRep,
    388                            PKIX_ESCASCII,
    389                            (void **)&asciiString,
    390                            &escAsciiLength,
    391                            plContext),
    392                            PKIX_STRINGGETENCODEDFAILED);
    393 
    394                PKIX_DATE_DEBUG("\t\tCalling DER_AsciiToTime).\n");
    395                /* DER_AsciiToTime only supports UTCTime (2-digit years) */
    396                rv = DER_AsciiToTime(&time, asciiString);
    397                if (rv != SECSuccess){
    398                        PKIX_ERROR(PKIX_DERASCIITOTIMEFAILED);
    399                }
    400        }
    401 
    402        /* create a PKIX_PL_Date object */
    403        PKIX_CHECK(PKIX_PL_Object_Alloc
    404                    (PKIX_DATE_TYPE,
    405                    sizeof (PKIX_PL_Date),
    406                    (PKIX_PL_Object **)&date,
    407                    plContext),
    408                    PKIX_COULDNOTCREATEOBJECT);
    409 
    410        /* populate the nssTime field */
    411        date->nssTime = time;
    412        *pDate = date;
    413 
    414 cleanup:
    415        PKIX_FREE(asciiString);
    416 
    417        PKIX_RETURN(DATE);
    418 }
    419 
    420 /*
    421 * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds
    422 * (see comments in pkix_pl_pki.h)
    423 */
    424 PKIX_Error *
    425 PKIX_PL_Date_Create_CurrentOffBySeconds(
    426        PKIX_Int32 secondsOffset,
    427        PKIX_PL_Date **pDate,
    428        void *plContext)
    429 {
    430        PKIX_PL_Date *date = NULL;
    431        PRTime time;
    432 
    433        PKIX_ENTER(DATE, "PKIX_PL_Date_Create_CurrentOffBySeconds");
    434        PKIX_NULLCHECK_ONE(pDate);
    435 
    436        time = PR_Now() + PR_SecondsToInterval(secondsOffset);
    437        /* create a PKIX_PL_Date object */
    438        PKIX_CHECK(PKIX_PL_Object_Alloc
    439                    (PKIX_DATE_TYPE,
    440                    sizeof (PKIX_PL_Date),
    441                    (PKIX_PL_Object **)&date,
    442                    plContext),
    443                    PKIX_COULDNOTCREATEOBJECT);
    444 
    445        /* populate the nssTime field */
    446        date->nssTime = time;
    447        *pDate = date;
    448 
    449 cleanup:
    450        PKIX_RETURN(DATE);
    451 }
    452 
    453 PKIX_Error *
    454 PKIX_PL_Date_CreateFromPRTime(
    455        PRTime prtime,
    456        PKIX_PL_Date **pDate,
    457        void *plContext)
    458 {
    459    PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime");
    460    PKIX_CHECK(
    461        pkix_pl_Date_CreateFromPRTime(prtime, pDate, plContext),
    462        PKIX_DATECREATEFROMPRTIMEFAILED);
    463 
    464 cleanup:
    465    PKIX_RETURN(DATE);
    466 }