Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_date.c
blob6427f8384936e3ce8fddd4736c61d071b28f0270
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 Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Sun Microsystems
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.destructor = pkix_pl_Date_Destroy;
439 entry.equalsFunction = pkix_pl_Date_Equals;
440 entry.hashcodeFunction = pkix_pl_Date_Hashcode;
441 entry.toStringFunction = pkix_pl_Date_ToString;
442 entry.comparator = pkix_pl_Date_Comparator;
443 entry.duplicateFunction = pkix_duplicateImmutable;
445 systemClasses[PKIX_DATE_TYPE] = entry;
447 PKIX_RETURN(DATE);
450 /* --Public-Functions------------------------------------------------------- */
453 * FUNCTION: PKIX_PL_Date_Create_UTCTime (see comments in pkix_pl_pki.h)
455 PKIX_Error *
456 PKIX_PL_Date_Create_UTCTime(
457 PKIX_PL_String *stringRep,
458 PKIX_PL_Date **pDate,
459 void *plContext)
461 PKIX_PL_Date *date = NULL;
462 char *asciiString = NULL;
463 PKIX_UInt32 escAsciiLength;
464 SECItem nssTime;
465 SECStatus rv;
466 PRTime time;
468 PKIX_ENTER(DATE, "PKIX_PL_Date_Create_UTCTime");
469 PKIX_NULLCHECK_ONE(pDate);
471 if (stringRep == NULL){
472 PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n");
473 time = PR_Now();
474 } else {
475 /* convert the input PKIX_PL_String to PKIX_ESCASCII */
476 PKIX_CHECK(PKIX_PL_String_GetEncoded
477 (stringRep,
478 PKIX_ESCASCII,
479 (void **)&asciiString,
480 &escAsciiLength,
481 plContext),
482 PKIX_STRINGGETENCODEDFAILED);
484 PKIX_DATE_DEBUG("\t\tCalling DER_AsciiToTime).\n");
485 /* DER_AsciiToTime only supports UTCTime (2-digit years) */
486 rv = DER_AsciiToTime(&time, asciiString);
487 if (rv != SECSuccess){
488 PKIX_ERROR(PKIX_DERASCIITOTIMEFAILED);
492 PKIX_DATE_DEBUG("\t\tCalling DER_TimeToUTCTime).\n");
493 rv = DER_TimeToUTCTime(&nssTime, time);
494 if (rv != SECSuccess){
495 PKIX_ERROR(PKIX_DERTIMETOUTCTIMEFAILED);
498 /* create a PKIX_PL_Date object */
499 PKIX_CHECK(PKIX_PL_Object_Alloc
500 (PKIX_DATE_TYPE,
501 sizeof (PKIX_PL_Date),
502 (PKIX_PL_Object **)&date,
503 plContext),
504 PKIX_COULDNOTCREATEOBJECT);
506 /* populate the nssTime field */
507 date->nssTime = nssTime;
509 *pDate = date;
511 cleanup:
513 PKIX_FREE(asciiString);
515 if (PKIX_ERROR_RECEIVED){
516 PR_Free(nssTime.data);
519 PKIX_RETURN(DATE);
523 * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds
524 * (see comments in pkix_pl_pki.h)
526 PKIX_Error *
527 PKIX_PL_Date_Create_CurrentOffBySeconds(
528 PKIX_Int32 secondsOffset,
529 PKIX_PL_Date **pDate,
530 void *plContext)
532 PKIX_PL_Date *date = NULL;
533 SECItem nssTime;
534 SECStatus rv;
535 PRTime time;
537 PKIX_ENTER(DATE, "PKIX_PL_Date_Create_CurrentOffBySeconds");
538 PKIX_NULLCHECK_ONE(pDate);
540 PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n");
541 time = PR_Now();
543 time += (secondsOffset * PR_USEC_PER_SEC);
545 PKIX_DATE_DEBUG("\t\tCalling DER_TimeToUTCTime).\n");
546 rv = DER_TimeToUTCTime(&nssTime, time);
547 if (rv != SECSuccess){
548 PKIX_ERROR(PKIX_DERTIMETOUTCTIMEFAILED);
551 /* create a PKIX_PL_Date object */
552 PKIX_CHECK(PKIX_PL_Object_Alloc
553 (PKIX_DATE_TYPE,
554 sizeof (PKIX_PL_Date),
555 (PKIX_PL_Object **)&date,
556 plContext),
557 PKIX_COULDNOTCREATEOBJECT);
559 /* populate the nssTime field */
560 date->nssTime = nssTime;
562 *pDate = date;
564 cleanup:
566 if (PKIX_ERROR_RECEIVED){
567 PR_Free(nssTime.data);
570 PKIX_RETURN(DATE);