nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_date.c
blobd5b5998df6278d495836260ec598469aa4b6ee80
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
12 * License.
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.
21 * Contributor(s):
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 ***** */
38 * pkix_pl_date.c
40 * Date Object Definitions
44 #include "pkix_pl_date.h"
46 /* --Private-Date-Functions------------------------------------- */
48 * FUNCTION: pkix_pl_Date_GetPRTime
49 * DESCRIPTION:
51 * Translates into a PRTime the Date embodied by the Date object pointed to
52 * by "date", and stores it at "pPRTime".
54 * PARAMETERS
55 * "date"
56 * Address of Date whose PRTime representation is desired. Must be
57 * non-NULL.
58 * "pPRTime"
59 * Address where PRTime value will be stored. Must be non-NULL.
60 * "plContext" - Platform-specific context pointer.
61 * THREAD SAFETY:
62 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
63 * RETURNS:
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.
68 PKIX_Error *
69 pkix_pl_Date_GetPRTime(
70 PKIX_PL_Date *date,
71 PRTime *pPRTime,
72 void *plContext)
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);
86 cleanup:
88 PKIX_RETURN(DATE);
92 * FUNCTION: pkix_pl_Date_CreateFromPRTime
93 * DESCRIPTION:
95 * Creates a new Date from the PRTime whose value is "prtime", and stores the
96 * result at "pDate".
98 * PARAMETERS
99 * "prtime"
100 * The PRTime value to be embodied in the new Date object.
101 * "pDate"
102 * Address where object pointer will be stored. Must be non-NULL.
103 * "plContext" - Platform-specific context pointer.
104 * THREAD SAFETY:
105 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
106 * RETURNS:
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.
111 PKIX_Error *
112 pkix_pl_Date_CreateFromPRTime(
113 PRTime prtime,
114 PKIX_PL_Date **pDate,
115 void *plContext)
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
133 (PKIX_DATE_TYPE,
134 sizeof (PKIX_PL_Date),
135 (PKIX_PL_Object **)&date,
136 plContext),
137 PKIX_COULDNOTCREATEOBJECT);
139 /* populate the nssTime field */
140 date->nssTime = nssTime;
142 *pDate = date;
144 cleanup:
146 if (PKIX_ERROR_RECEIVED){
147 PR_Free(nssTime.data);
150 PKIX_RETURN(DATE);
154 * FUNCTION: pkix_pl_Date_ToString_Helper
155 * DESCRIPTION:
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".
160 * PARAMETERS
161 * "nssTime"
162 * Address of SECItem whose string representation is desired.
163 * Must be non-NULL.
164 * "pString"
165 * Address where object pointer will be stored. Must be non-NULL.
166 * "plContext" - Platform-specific context pointer.
167 * THREAD SAFETY:
168 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
169 * RETURNS:
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.
174 PKIX_Error *
175 pkix_pl_Date_ToString_Helper(
176 SECItem *nssTime,
177 PKIX_PL_String **pString,
178 void *plContext)
180 char *asciiDate = NULL;
182 PKIX_ENTER(DATE, "pkix_pl_Date_ToString_Helper");
183 PKIX_NULLCHECK_TWO(nssTime, pString);
185 switch (nssTime->type) {
186 case siUTCTime:
187 PKIX_PL_NSSCALLRV
188 (DATE, asciiDate, DER_UTCDayToAscii, (nssTime));
189 if (!asciiDate){
190 PKIX_ERROR(PKIX_DERUTCTIMETOASCIIFAILED);
192 break;
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.
199 PKIX_PL_NSSCALLRV
200 (DATE, asciiDate, DER_GeneralizedDayToAscii, (nssTime));
201 if (!asciiDate){
202 PKIX_ERROR(PKIX_DERGENERALIZEDDAYTOASCIIFAILED);
204 break;
205 default:
206 PKIX_ERROR(PKIX_UNRECOGNIZEDTIMETYPE);
209 PKIX_CHECK(PKIX_PL_String_Create
210 (PKIX_ESCASCII, asciiDate, 0, pString, plContext),
211 PKIX_STRINGCREATEFAILED);
213 cleanup:
215 PR_Free(asciiDate);
217 PKIX_RETURN(DATE);
222 * FUNCTION: pkix_pl_Date_Destroy
223 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
225 static PKIX_Error *
226 pkix_pl_Date_Destroy(
227 PKIX_PL_Object *object,
228 void *plContext)
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),
236 PKIX_OBJECTNOTDATE);
238 date = (PKIX_PL_Date *)object;
240 PR_Free(date->nssTime.data);
242 cleanup:
244 PKIX_RETURN(DATE);
248 * FUNCTION: pkix_pl_Date_ToString
249 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
251 static PKIX_Error *
252 pkix_pl_Date_ToString(
253 PKIX_PL_Object *object,
254 PKIX_PL_String **pString,
255 void *plContext)
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),
266 PKIX_OBJECTNOTDATE);
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;
278 cleanup:
280 PKIX_FREE(asciiDate);
282 PKIX_RETURN(DATE);
286 * FUNCTION: pkix_pl_Date_Hashcode
287 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
289 static PKIX_Error *
290 pkix_pl_Date_Hashcode(
291 PKIX_PL_Object *object,
292 PKIX_UInt32 *pHashcode,
293 void *plContext)
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),
303 PKIX_OBJECTNOTDATE);
305 date = (PKIX_PL_Date *)object;
307 nssTime = &date->nssTime;
309 PKIX_CHECK
310 (pkix_hash
311 ((const unsigned char *)nssTime->data,
312 nssTime->len,
313 &dateHash,
314 plContext),
315 PKIX_HASHFAILED);
317 *pHashcode = dateHash;
319 cleanup:
321 PKIX_RETURN(DATE);
326 * FUNCTION: pkix_pl_Date_Comparator
327 * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
329 static PKIX_Error *
330 pkix_pl_Date_Comparator(
331 PKIX_PL_Object *firstObject,
332 PKIX_PL_Object *secondObject,
333 PKIX_Int32 *pResult,
334 void *plContext)
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;
355 cleanup:
357 PKIX_RETURN(DATE);
361 * FUNCTION: pkix_pl_Date_Equals
362 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
364 static PKIX_Error *
365 pkix_pl_Date_Equals(
366 PKIX_PL_Object *firstObject,
367 PKIX_PL_Object *secondObject,
368 PKIX_Boolean *pResult,
369 void *plContext)
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;
392 goto cleanup;
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);
413 cleanup:
415 PKIX_RETURN(DATE);
419 * FUNCTION: pkix_pl_Date_RegisterSelf
420 * DESCRIPTION:
421 * Registers PKIX_DATE_TYPE and its related functions with systemClasses[]
422 * THREAD SAFETY:
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
427 * thread-safe.
429 PKIX_Error *
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;
449 PKIX_RETURN(DATE);
452 /* --Public-Functions------------------------------------------------------- */
455 * FUNCTION: PKIX_PL_Date_Create_UTCTime (see comments in pkix_pl_pki.h)
457 PKIX_Error *
458 PKIX_PL_Date_Create_UTCTime(
459 PKIX_PL_String *stringRep,
460 PKIX_PL_Date **pDate,
461 void *plContext)
463 PKIX_PL_Date *date = NULL;
464 char *asciiString = NULL;
465 PKIX_UInt32 escAsciiLength;
466 SECItem nssTime;
467 SECStatus rv;
468 PRTime time;
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");
475 time = PR_Now();
476 } else {
477 /* convert the input PKIX_PL_String to PKIX_ESCASCII */
478 PKIX_CHECK(PKIX_PL_String_GetEncoded
479 (stringRep,
480 PKIX_ESCASCII,
481 (void **)&asciiString,
482 &escAsciiLength,
483 plContext),
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
502 (PKIX_DATE_TYPE,
503 sizeof (PKIX_PL_Date),
504 (PKIX_PL_Object **)&date,
505 plContext),
506 PKIX_COULDNOTCREATEOBJECT);
508 /* populate the nssTime field */
509 date->nssTime = nssTime;
511 *pDate = date;
513 cleanup:
515 PKIX_FREE(asciiString);
517 if (PKIX_ERROR_RECEIVED){
518 PR_Free(nssTime.data);
521 PKIX_RETURN(DATE);
525 * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds
526 * (see comments in pkix_pl_pki.h)
528 PKIX_Error *
529 PKIX_PL_Date_Create_CurrentOffBySeconds(
530 PKIX_Int32 secondsOffset,
531 PKIX_PL_Date **pDate,
532 void *plContext)
534 PKIX_PL_Date *date = NULL;
535 SECItem nssTime;
536 SECStatus rv;
537 PRTime time;
539 PKIX_ENTER(DATE, "PKIX_PL_Date_Create_CurrentOffBySeconds");
540 PKIX_NULLCHECK_ONE(pDate);
542 PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n");
543 time = PR_Now();
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
555 (PKIX_DATE_TYPE,
556 sizeof (PKIX_PL_Date),
557 (PKIX_PL_Object **)&date,
558 plContext),
559 PKIX_COULDNOTCREATEOBJECT);
561 /* populate the nssTime field */
562 date->nssTime = nssTime;
564 *pDate = date;
566 cleanup:
568 if (PKIX_ERROR_RECEIVED){
569 PR_Free(nssTime.data);
572 PKIX_RETURN(DATE);
575 PKIX_Error *
576 PKIX_PL_Date_CreateFromPRTime(
577 PRTime prtime,
578 PKIX_PL_Date **pDate,
579 void *plContext)
581 PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime");
582 PKIX_CHECK(
583 pkix_pl_Date_CreateFromPRTime(prtime, pDate, plContext),
584 PKIX_DATECREATEFROMPRTIMEFAILED);
586 cleanup:
587 PKIX_RETURN(DATE);