| OLD | NEW |
| (Empty) |
| 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 } | |
| OLD | NEW |