diff nss/lib/util/dertime.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nss/lib/util/dertime.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,310 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "secder.h"
+#include "prlong.h"
+#include "secerr.h"
+
+#define HIDIGIT(v) (((v) / 10) + '0')
+#define LODIGIT(v) (((v) % 10) + '0')
+
+#define ISDIGIT(dig) (((dig) >= '0') && ((dig) <= '9'))
+#define CAPTURE(var,p,label)				  \
+{							  \
+    if (!ISDIGIT((p)[0]) || !ISDIGIT((p)[1])) goto label; \
+    (var) = ((p)[0] - '0') * 10 + ((p)[1] - '0');	  \
+    p += 2; \
+}
+
+static const PRTime January1st1     = (PRTime) LL_INIT(0xff234001U, 0x00d44000U);
+static const PRTime January1st1950  = (PRTime) LL_INIT(0xfffdc1f8U, 0x793da000U);
+static const PRTime January1st2050  = LL_INIT(0x0008f81e, 0x1b098000);
+static const PRTime January1st10000 = LL_INIT(0x0384440c, 0xcc736000);
+
+/* gmttime must contains UTC time in micro-seconds unit */
+SECStatus
+DER_TimeToUTCTimeArena(PLArenaPool* arenaOpt, SECItem *dst, PRTime gmttime)
+{
+    PRExplodedTime printableTime;
+    unsigned char *d;
+
+    if ( (gmttime < January1st1950) || (gmttime >= January1st2050) ) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    dst->len = 13;
+    if (arenaOpt) {
+        dst->data = d = (unsigned char*) PORT_ArenaAlloc(arenaOpt, dst->len);
+    } else {
+        dst->data = d = (unsigned char*) PORT_Alloc(dst->len);
+    }
+    dst->type = siUTCTime;
+    if (!d) {
+	return SECFailure;
+    }
+
+    /* Convert a PRTime to a printable format.  */
+    PR_ExplodeTime(gmttime, PR_GMTParameters, &printableTime);
+
+    /* The month in UTC time is base one */
+    printableTime.tm_month++;
+
+    /* remove the century since it's added to the tm_year by the 
+       PR_ExplodeTime routine, but is not needed for UTC time */
+    printableTime.tm_year %= 100; 
+
+    d[0] = HIDIGIT(printableTime.tm_year);
+    d[1] = LODIGIT(printableTime.tm_year);
+    d[2] = HIDIGIT(printableTime.tm_month);
+    d[3] = LODIGIT(printableTime.tm_month);
+    d[4] = HIDIGIT(printableTime.tm_mday);
+    d[5] = LODIGIT(printableTime.tm_mday);
+    d[6] = HIDIGIT(printableTime.tm_hour);
+    d[7] = LODIGIT(printableTime.tm_hour);
+    d[8] = HIDIGIT(printableTime.tm_min);
+    d[9] = LODIGIT(printableTime.tm_min);
+    d[10] = HIDIGIT(printableTime.tm_sec);
+    d[11] = LODIGIT(printableTime.tm_sec);
+    d[12] = 'Z';
+    return SECSuccess;
+}
+
+SECStatus
+DER_TimeToUTCTime(SECItem *dst, PRTime gmttime)
+{
+    return DER_TimeToUTCTimeArena(NULL, dst, gmttime);
+}
+
+static SECStatus /* forward */
+der_TimeStringToTime(PRTime *dst, const char *string, int generalized,
+                     const char **endptr);
+
+#define GEN_STRING 2 /* TimeString is a GeneralizedTime */
+#define UTC_STRING 0 /* TimeString is a UTCTime         */
+
+/* The caller of DER_AsciiToItem MUST ENSURE that either
+** a) "string" points to a null-terminated ASCII string, or
+** b) "string" points to a buffer containing a valid UTCTime, 
+**     whether null terminated or not, or
+** c) "string" contains at least 19 characters, with or without null char.
+** otherwise, this function may UMR and/or crash.
+** It suffices to ensure that the input "string" is at least 17 bytes long.
+*/
+SECStatus
+DER_AsciiToTime(PRTime *dst, const char *string)
+{
+    return der_TimeStringToTime(dst, string, UTC_STRING, NULL);
+}
+
+SECStatus
+DER_UTCTimeToTime(PRTime *dst, const SECItem *time)
+{
+    /* Minimum valid UTCTime is yymmddhhmmZ       which is 11 bytes. 
+    ** Maximum valid UTCTime is yymmddhhmmss+0000 which is 17 bytes.
+    ** 20 should be large enough for all valid encoded times. 
+    */
+    unsigned int i;
+    char localBuf[20];
+    const char *end = NULL;
+    SECStatus rv;
+
+    if (!time || !time->data || time->len < 11 || time->len > 17) {
+	PORT_SetError(SEC_ERROR_INVALID_TIME);
+	return SECFailure;
+    }
+
+    for (i = 0; i < time->len; i++) {
+	if (time->data[i] == '\0') {
+	    PORT_SetError(SEC_ERROR_INVALID_TIME);
+	    return SECFailure;
+	}
+	localBuf[i] = time->data[i];
+    }
+    localBuf[i] = '\0';
+
+    rv = der_TimeStringToTime(dst, localBuf, UTC_STRING, &end);
+    if (rv == SECSuccess && *end != '\0') {
+	PORT_SetError(SEC_ERROR_INVALID_TIME);
+	return SECFailure;
+    }
+    return rv;
+}
+
+/*
+   gmttime must contains UTC time in micro-seconds unit.
+   Note: the caller should make sure that Generalized time
+   should only be used for certifiate validities after the
+   year 2049.  Otherwise, UTC time should be used.  This routine
+   does not check this case, since it can be used to encode
+   certificate extension, which does not have this restriction. 
+ */
+SECStatus
+DER_TimeToGeneralizedTimeArena(PLArenaPool* arenaOpt, SECItem *dst, PRTime gmttime)
+{
+    PRExplodedTime printableTime;
+    unsigned char *d;
+
+    if ( (gmttime<January1st1) || (gmttime>=January1st10000) ) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+    dst->len = 15;
+    if (arenaOpt) {
+        dst->data = d = (unsigned char*) PORT_ArenaAlloc(arenaOpt, dst->len);
+    } else {
+        dst->data = d = (unsigned char*) PORT_Alloc(dst->len);
+    }
+    dst->type = siGeneralizedTime;
+    if (!d) {
+	return SECFailure;
+    }
+
+    /* Convert a PRTime to a printable format.  */
+    PR_ExplodeTime(gmttime, PR_GMTParameters, &printableTime);
+
+    /* The month in Generalized time is base one */
+    printableTime.tm_month++;
+
+    d[0] = (printableTime.tm_year /1000) + '0';
+    d[1] = ((printableTime.tm_year % 1000) / 100) + '0';
+    d[2] = ((printableTime.tm_year % 100) / 10) + '0';
+    d[3] = (printableTime.tm_year % 10) + '0';
+    d[4] = HIDIGIT(printableTime.tm_month);
+    d[5] = LODIGIT(printableTime.tm_month);
+    d[6] = HIDIGIT(printableTime.tm_mday);
+    d[7] = LODIGIT(printableTime.tm_mday);
+    d[8] = HIDIGIT(printableTime.tm_hour);
+    d[9] = LODIGIT(printableTime.tm_hour);
+    d[10] = HIDIGIT(printableTime.tm_min);
+    d[11] = LODIGIT(printableTime.tm_min);
+    d[12] = HIDIGIT(printableTime.tm_sec);
+    d[13] = LODIGIT(printableTime.tm_sec);
+    d[14] = 'Z';
+    return SECSuccess;
+}
+
+SECStatus
+DER_TimeToGeneralizedTime(SECItem *dst, PRTime gmttime)
+{
+    return DER_TimeToGeneralizedTimeArena(NULL, dst, gmttime);
+}
+
+
+SECStatus
+DER_GeneralizedTimeToTime(PRTime *dst, const SECItem *time)
+{
+    /* Minimum valid GeneralizedTime is ccyymmddhhmmZ       which is 13 bytes.
+    ** Maximum valid GeneralizedTime is ccyymmddhhmmss+0000 which is 19 bytes.
+    ** 20 should be large enough for all valid encoded times. 
+    */
+    unsigned int i;
+    char localBuf[20];
+    const char *end = NULL;
+    SECStatus rv;
+
+    if (!time || !time->data || time->len < 13 || time->len > 19) {
+	PORT_SetError(SEC_ERROR_INVALID_TIME);
+	return SECFailure;
+    }
+
+    for (i = 0; i < time->len; i++) {
+	if (time->data[i] == '\0') {
+	    PORT_SetError(SEC_ERROR_INVALID_TIME);
+	    return SECFailure;
+	}
+	localBuf[i] = time->data[i];
+    }
+    localBuf[i] = '\0';
+
+    rv = der_TimeStringToTime(dst, localBuf, GEN_STRING, &end);
+    if (rv == SECSuccess && *end != '\0') {
+	PORT_SetError(SEC_ERROR_INVALID_TIME);
+	return SECFailure;
+    }
+    return rv;
+}
+
+static SECStatus
+der_TimeStringToTime(PRTime *dst, const char *string, int generalized,
+                     const char **endptr)
+{
+    PRExplodedTime genTime;
+    long hourOff = 0, minOff = 0;
+    PRUint16 century;
+    char signum;
+
+    if (string == NULL || dst == NULL) {
+	PORT_SetError(SEC_ERROR_INVALID_ARGS);
+	return SECFailure;
+    }
+
+    /* Verify time is formatted properly and capture information */
+    memset(&genTime, 0, sizeof genTime);
+
+    if (generalized == UTC_STRING) {
+	CAPTURE(genTime.tm_year, string, loser);
+	century = (genTime.tm_year < 50) ? 20 : 19;
+    } else {
+	CAPTURE(century, string, loser);
+	CAPTURE(genTime.tm_year, string, loser);
+    }
+    genTime.tm_year += century * 100;
+
+    CAPTURE(genTime.tm_month, string, loser);
+    if ((genTime.tm_month == 0) || (genTime.tm_month > 12)) 
+    	goto loser;
+
+    /* NSPR month base is 0 */
+    --genTime.tm_month;
+    
+    CAPTURE(genTime.tm_mday, string, loser);
+    if ((genTime.tm_mday == 0) || (genTime.tm_mday > 31)) 
+    	goto loser;
+    
+    CAPTURE(genTime.tm_hour, string, loser);
+    if (genTime.tm_hour > 23) 
+    	goto loser;
+    
+    CAPTURE(genTime.tm_min, string, loser);
+    if (genTime.tm_min > 59) 
+    	goto loser;
+    
+    if (ISDIGIT(string[0])) {
+	CAPTURE(genTime.tm_sec, string, loser);
+	if (genTime.tm_sec > 59) 
+	    goto loser;
+    }
+    signum = *string++;
+    if (signum == '+' || signum == '-') {
+	CAPTURE(hourOff, string, loser);
+	if (hourOff > 23) 
+	    goto loser;
+	CAPTURE(minOff, string, loser);
+	if (minOff > 59) 
+	    goto loser;
+	if (signum == '-') {
+	    hourOff = -hourOff;
+	    minOff  = -minOff;
+	}
+    } else if (signum != 'Z') {
+	goto loser;
+    }
+
+    if (endptr)
+    	*endptr = string;
+
+    /* Convert the GMT offset to seconds and save it in genTime
+     * for the implode time call.
+     */
+    genTime.tm_params.tp_gmt_offset = (PRInt32)((hourOff * 60L + minOff) * 60L);
+    *dst = PR_ImplodeTime(&genTime);
+    return SECSuccess;
+
+loser:
+    PORT_SetError(SEC_ERROR_INVALID_TIME);
+    return SECFailure;
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)