1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
40 * Date Object Definitions
44 #include "pkix_pl_date.h"
46 /* --Private-Date-Functions------------------------------------- */
48 * FUNCTION: pkix_pl_Date_GetPRTime
51 * Translates into a PRTime the Date embodied by the Date object pointed to
52 * by "date", and stores it at "pPRTime".
56 * Address of Date whose PRTime representation is desired. Must be
59 * Address where PRTime value will be stored. Must be non-NULL.
60 * "plContext" - Platform-specific context pointer.
62 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
64 * Returns NULL if the function succeeds.
65 * Returns a Date Error if the function fails in a non-fatal way.
66 * Returns a Fatal Error if the function fails in an unrecoverable way.
69 pkix_pl_Date_GetPRTime(
74 SECStatus rv
= SECFailure
;
76 PKIX_ENTER(DATE
, "PKIX_PL_Date_GetPRTime");
77 PKIX_NULLCHECK_TWO(date
, pPRTime
);
79 PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n");
80 rv
= DER_DecodeTimeChoice(pPRTime
, &date
->nssTime
);
82 if (rv
== SECFailure
) {
83 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED
);
92 * FUNCTION: pkix_pl_Date_CreateFromPRTime
95 * Creates a new Date from the PRTime whose value is "prtime", and stores the
100 * The PRTime value to be embodied in the new Date object.
102 * Address where object pointer will be stored. Must be non-NULL.
103 * "plContext" - Platform-specific context pointer.
105 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
107 * Returns NULL if the function succeeds.
108 * Returns a Date Error if the function fails in a non-fatal way.
109 * Returns a Fatal Error if the function fails in an unrecoverable way.
112 pkix_pl_Date_CreateFromPRTime(
114 PKIX_PL_Date
**pDate
,
117 SECItem nssTime
= { 0, NULL
, 0 };
118 SECStatus rv
= SECFailure
;
119 PKIX_PL_Date
*date
= NULL
;
121 PKIX_ENTER(DATE
, "PKIX_PL_Date_CreateFromPRTime");
122 PKIX_NULLCHECK_ONE(pDate
);
124 PKIX_DATE_DEBUG("\t\tCalling DER_EncodeTimeChoice).\n");
125 rv
= DER_EncodeTimeChoice(NULL
, &nssTime
, prtime
);
127 if (rv
== SECFailure
) {
128 PKIX_ERROR(PKIX_DERENCODETIMECHOICEFAILED
);
131 /* create a PKIX_PL_Date object */
132 PKIX_CHECK(PKIX_PL_Object_Alloc
134 sizeof (PKIX_PL_Date
),
135 (PKIX_PL_Object
**)&date
,
137 PKIX_COULDNOTCREATEOBJECT
);
139 /* populate the nssTime field */
140 date
->nssTime
= nssTime
;
146 if (PKIX_ERROR_RECEIVED
){
147 PR_Free(nssTime
.data
);
154 * FUNCTION: pkix_pl_Date_ToString_Helper
157 * Helper function that creates a string representation of the SECItem pointed
158 * to by "nssTime" (which represents a date) and stores it at "pString".
162 * Address of SECItem whose string representation is desired.
165 * Address where object pointer will be stored. Must be non-NULL.
166 * "plContext" - Platform-specific context pointer.
168 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
170 * Returns NULL if the function succeeds.
171 * Returns a Date Error if the function fails in a non-fatal way.
172 * Returns a Fatal Error if the function fails in an unrecoverable way.
175 pkix_pl_Date_ToString_Helper(
177 PKIX_PL_String
**pString
,
180 char *asciiDate
= NULL
;
182 PKIX_ENTER(DATE
, "pkix_pl_Date_ToString_Helper");
183 PKIX_NULLCHECK_TWO(nssTime
, pString
);
185 switch (nssTime
->type
) {
188 (DATE
, asciiDate
, DER_UTCDayToAscii
, (nssTime
));
190 PKIX_ERROR(PKIX_DERUTCTIMETOASCIIFAILED
);
193 case siGeneralizedTime
:
195 * we don't currently have any way to create GeneralizedTime.
196 * this code is only here so that it will be in place when
197 * we do have the capability to create GeneralizedTime.
200 (DATE
, asciiDate
, DER_GeneralizedDayToAscii
, (nssTime
));
202 PKIX_ERROR(PKIX_DERGENERALIZEDDAYTOASCIIFAILED
);
206 PKIX_ERROR(PKIX_UNRECOGNIZEDTIMETYPE
);
209 PKIX_CHECK(PKIX_PL_String_Create
210 (PKIX_ESCASCII
, asciiDate
, 0, pString
, plContext
),
211 PKIX_STRINGCREATEFAILED
);
222 * FUNCTION: pkix_pl_Date_Destroy
223 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
226 pkix_pl_Date_Destroy(
227 PKIX_PL_Object
*object
,
230 PKIX_PL_Date
*date
= NULL
;
232 PKIX_ENTER(DATE
, "pkix_pl_Date_Destroy");
233 PKIX_NULLCHECK_ONE(object
);
235 PKIX_CHECK(pkix_CheckType(object
, PKIX_DATE_TYPE
, plContext
),
238 date
= (PKIX_PL_Date
*)object
;
240 PR_Free(date
->nssTime
.data
);
248 * FUNCTION: pkix_pl_Date_ToString
249 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
252 pkix_pl_Date_ToString(
253 PKIX_PL_Object
*object
,
254 PKIX_PL_String
**pString
,
257 PKIX_PL_String
*dateString
= NULL
;
258 PKIX_PL_Date
*date
= NULL
;
259 SECItem
*nssTime
= NULL
;
260 char *asciiDate
= NULL
;
262 PKIX_ENTER(DATE
, "pkix_pl_Date_toString");
263 PKIX_NULLCHECK_TWO(object
, pString
);
265 PKIX_CHECK(pkix_CheckType(object
, PKIX_DATE_TYPE
, plContext
),
268 date
= (PKIX_PL_Date
*)object
;
270 nssTime
= &date
->nssTime
;
272 PKIX_CHECK(pkix_pl_Date_ToString_Helper
273 (nssTime
, &dateString
, plContext
),
274 PKIX_DATETOSTRINGHELPERFAILED
);
276 *pString
= dateString
;
280 PKIX_FREE(asciiDate
);
286 * FUNCTION: pkix_pl_Date_Hashcode
287 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
290 pkix_pl_Date_Hashcode(
291 PKIX_PL_Object
*object
,
292 PKIX_UInt32
*pHashcode
,
295 PKIX_PL_Date
*date
= NULL
;
296 SECItem
*nssTime
= NULL
;
297 PKIX_UInt32 dateHash
;
299 PKIX_ENTER(DATE
, "pkix_pl_Date_Hashcode");
300 PKIX_NULLCHECK_TWO(object
, pHashcode
);
302 PKIX_CHECK(pkix_CheckType(object
, PKIX_DATE_TYPE
, plContext
),
305 date
= (PKIX_PL_Date
*)object
;
307 nssTime
= &date
->nssTime
;
311 ((const unsigned char *)nssTime
->data
,
317 *pHashcode
= dateHash
;
326 * FUNCTION: pkix_pl_Date_Comparator
327 * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
330 pkix_pl_Date_Comparator(
331 PKIX_PL_Object
*firstObject
,
332 PKIX_PL_Object
*secondObject
,
336 SECItem
*firstTime
= NULL
;
337 SECItem
*secondTime
= NULL
;
338 SECComparison cmpResult
;
340 PKIX_ENTER(DATE
, "pkix_pl_Date_Comparator");
341 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
343 PKIX_CHECK(pkix_CheckTypes
344 (firstObject
, secondObject
, PKIX_DATE_TYPE
, plContext
),
345 PKIX_ARGUMENTSNOTDATES
);
347 firstTime
= &((PKIX_PL_Date
*)firstObject
)->nssTime
;
348 secondTime
= &((PKIX_PL_Date
*)secondObject
)->nssTime
;
350 PKIX_DATE_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
351 cmpResult
= SECITEM_CompareItem(firstTime
, secondTime
);
353 *pResult
= cmpResult
;
361 * FUNCTION: pkix_pl_Date_Equals
362 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
366 PKIX_PL_Object
*firstObject
,
367 PKIX_PL_Object
*secondObject
,
368 PKIX_Boolean
*pResult
,
372 /* note: pkix_pl_Date can only represent UTCTime,not GeneralizedTime */
374 SECItem
*firstTime
= NULL
;
375 SECItem
*secondTime
= NULL
;
376 PKIX_UInt32 secondType
;
377 SECComparison cmpResult
;
379 PKIX_ENTER(DATE
, "pkix_pl_Date_Equals");
380 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
382 /* test that firstObject is a Date */
383 PKIX_CHECK(pkix_CheckType(firstObject
, PKIX_DATE_TYPE
, plContext
),
384 PKIX_FIRSTOBJECTNOTDATE
);
387 * Since we know firstObject is a Date, if both references are
388 * identical, they must be equal
390 if (firstObject
== secondObject
){
391 *pResult
= PKIX_TRUE
;
396 * If secondObject isn't a Date, we don't throw an error.
397 * We simply return a Boolean result of FALSE
399 *pResult
= PKIX_FALSE
;
400 PKIX_CHECK(PKIX_PL_Object_GetType
401 (secondObject
, &secondType
, plContext
),
402 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT
);
403 if (secondType
!= PKIX_DATE_TYPE
) goto cleanup
;
405 firstTime
= &((PKIX_PL_Date
*)firstObject
)->nssTime
;
406 secondTime
= &((PKIX_PL_Date
*)secondObject
)->nssTime
;
408 PKIX_DATE_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
409 cmpResult
= SECITEM_CompareItem(firstTime
, secondTime
);
411 *pResult
= (cmpResult
== SECEqual
);
419 * FUNCTION: pkix_pl_Date_RegisterSelf
421 * Registers PKIX_DATE_TYPE and its related functions with systemClasses[]
423 * Not Thread Safe - for performance and complexity reasons
425 * Since this function is only called by PKIX_PL_Initialize, which should
426 * only be called once, it is acceptable that this function is not
430 pkix_pl_Date_RegisterSelf(void *plContext
)
432 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
433 pkix_ClassTable_Entry entry
;
435 PKIX_ENTER(DATE
, "pkix_pl_Date_RegisterSelf");
437 entry
.description
= "Date";
438 entry
.objCounter
= 0;
439 entry
.typeObjectSize
= sizeof(PKIX_PL_Date
);
440 entry
.destructor
= pkix_pl_Date_Destroy
;
441 entry
.equalsFunction
= pkix_pl_Date_Equals
;
442 entry
.hashcodeFunction
= pkix_pl_Date_Hashcode
;
443 entry
.toStringFunction
= pkix_pl_Date_ToString
;
444 entry
.comparator
= pkix_pl_Date_Comparator
;
445 entry
.duplicateFunction
= pkix_duplicateImmutable
;
447 systemClasses
[PKIX_DATE_TYPE
] = entry
;
452 /* --Public-Functions------------------------------------------------------- */
455 * FUNCTION: PKIX_PL_Date_Create_UTCTime (see comments in pkix_pl_pki.h)
458 PKIX_PL_Date_Create_UTCTime(
459 PKIX_PL_String
*stringRep
,
460 PKIX_PL_Date
**pDate
,
463 PKIX_PL_Date
*date
= NULL
;
464 char *asciiString
= NULL
;
465 PKIX_UInt32 escAsciiLength
;
470 PKIX_ENTER(DATE
, "PKIX_PL_Date_Create_UTCTime");
471 PKIX_NULLCHECK_ONE(pDate
);
473 if (stringRep
== NULL
){
474 PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n");
477 /* convert the input PKIX_PL_String to PKIX_ESCASCII */
478 PKIX_CHECK(PKIX_PL_String_GetEncoded
481 (void **)&asciiString
,
484 PKIX_STRINGGETENCODEDFAILED
);
486 PKIX_DATE_DEBUG("\t\tCalling DER_AsciiToTime).\n");
487 /* DER_AsciiToTime only supports UTCTime (2-digit years) */
488 rv
= DER_AsciiToTime(&time
, asciiString
);
489 if (rv
!= SECSuccess
){
490 PKIX_ERROR(PKIX_DERASCIITOTIMEFAILED
);
494 PKIX_DATE_DEBUG("\t\tCalling DER_TimeToUTCTime).\n");
495 rv
= DER_TimeToUTCTime(&nssTime
, time
);
496 if (rv
!= SECSuccess
){
497 PKIX_ERROR(PKIX_DERTIMETOUTCTIMEFAILED
);
500 /* create a PKIX_PL_Date object */
501 PKIX_CHECK(PKIX_PL_Object_Alloc
503 sizeof (PKIX_PL_Date
),
504 (PKIX_PL_Object
**)&date
,
506 PKIX_COULDNOTCREATEOBJECT
);
508 /* populate the nssTime field */
509 date
->nssTime
= nssTime
;
515 PKIX_FREE(asciiString
);
517 if (PKIX_ERROR_RECEIVED
){
518 PR_Free(nssTime
.data
);
525 * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds
526 * (see comments in pkix_pl_pki.h)
529 PKIX_PL_Date_Create_CurrentOffBySeconds(
530 PKIX_Int32 secondsOffset
,
531 PKIX_PL_Date
**pDate
,
534 PKIX_PL_Date
*date
= NULL
;
539 PKIX_ENTER(DATE
, "PKIX_PL_Date_Create_CurrentOffBySeconds");
540 PKIX_NULLCHECK_ONE(pDate
);
542 PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n");
545 time
+= (secondsOffset
* PR_USEC_PER_SEC
);
547 PKIX_DATE_DEBUG("\t\tCalling DER_TimeToUTCTime).\n");
548 rv
= DER_TimeToUTCTime(&nssTime
, time
);
549 if (rv
!= SECSuccess
){
550 PKIX_ERROR(PKIX_DERTIMETOUTCTIMEFAILED
);
553 /* create a PKIX_PL_Date object */
554 PKIX_CHECK(PKIX_PL_Object_Alloc
556 sizeof (PKIX_PL_Date
),
557 (PKIX_PL_Object
**)&date
,
559 PKIX_COULDNOTCREATEOBJECT
);
561 /* populate the nssTime field */
562 date
->nssTime
= nssTime
;
568 if (PKIX_ERROR_RECEIVED
){
569 PR_Free(nssTime
.data
);
576 PKIX_PL_Date_CreateFromPRTime(
578 PKIX_PL_Date
**pDate
,
581 PKIX_ENTER(DATE
, "PKIX_PL_Date_CreateFromPRTime");
583 pkix_pl_Date_CreateFromPRTime(prtime
, pDate
, plContext
),
584 PKIX_DATECREATEFROMPRTIMEFAILED
);