comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
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 #include "prtypes.h"
6 #include "prtime.h"
7 #include "secder.h"
8 #include "prlong.h"
9 #include "secerr.h"
10
11 #define HIDIGIT(v) (((v) / 10) + '0')
12 #define LODIGIT(v) (((v) % 10) + '0')
13
14 #define ISDIGIT(dig) (((dig) >= '0') && ((dig) <= '9'))
15 #define CAPTURE(var,p,label) \
16 { \
17 if (!ISDIGIT((p)[0]) || !ISDIGIT((p)[1])) goto label; \
18 (var) = ((p)[0] - '0') * 10 + ((p)[1] - '0'); \
19 p += 2; \
20 }
21
22 static const PRTime January1st1 = (PRTime) LL_INIT(0xff234001U, 0x00d44000U);
23 static const PRTime January1st1950 = (PRTime) LL_INIT(0xfffdc1f8U, 0x793da000U);
24 static const PRTime January1st2050 = LL_INIT(0x0008f81e, 0x1b098000);
25 static const PRTime January1st10000 = LL_INIT(0x0384440c, 0xcc736000);
26
27 /* gmttime must contains UTC time in micro-seconds unit */
28 SECStatus
29 DER_TimeToUTCTimeArena(PLArenaPool* arenaOpt, SECItem *dst, PRTime gmttime)
30 {
31 PRExplodedTime printableTime;
32 unsigned char *d;
33
34 if ( (gmttime < January1st1950) || (gmttime >= January1st2050) ) {
35 PORT_SetError(SEC_ERROR_INVALID_ARGS);
36 return SECFailure;
37 }
38
39 dst->len = 13;
40 if (arenaOpt) {
41 dst->data = d = (unsigned char*) PORT_ArenaAlloc(arenaOpt, dst->len);
42 } else {
43 dst->data = d = (unsigned char*) PORT_Alloc(dst->len);
44 }
45 dst->type = siUTCTime;
46 if (!d) {
47 return SECFailure;
48 }
49
50 /* Convert a PRTime to a printable format. */
51 PR_ExplodeTime(gmttime, PR_GMTParameters, &printableTime);
52
53 /* The month in UTC time is base one */
54 printableTime.tm_month++;
55
56 /* remove the century since it's added to the tm_year by the
57 PR_ExplodeTime routine, but is not needed for UTC time */
58 printableTime.tm_year %= 100;
59
60 d[0] = HIDIGIT(printableTime.tm_year);
61 d[1] = LODIGIT(printableTime.tm_year);
62 d[2] = HIDIGIT(printableTime.tm_month);
63 d[3] = LODIGIT(printableTime.tm_month);
64 d[4] = HIDIGIT(printableTime.tm_mday);
65 d[5] = LODIGIT(printableTime.tm_mday);
66 d[6] = HIDIGIT(printableTime.tm_hour);
67 d[7] = LODIGIT(printableTime.tm_hour);
68 d[8] = HIDIGIT(printableTime.tm_min);
69 d[9] = LODIGIT(printableTime.tm_min);
70 d[10] = HIDIGIT(printableTime.tm_sec);
71 d[11] = LODIGIT(printableTime.tm_sec);
72 d[12] = 'Z';
73 return SECSuccess;
74 }
75
76 SECStatus
77 DER_TimeToUTCTime(SECItem *dst, PRTime gmttime)
78 {
79 return DER_TimeToUTCTimeArena(NULL, dst, gmttime);
80 }
81
82 static SECStatus /* forward */
83 der_TimeStringToTime(PRTime *dst, const char *string, int generalized,
84 const char **endptr);
85
86 #define GEN_STRING 2 /* TimeString is a GeneralizedTime */
87 #define UTC_STRING 0 /* TimeString is a UTCTime */
88
89 /* The caller of DER_AsciiToItem MUST ENSURE that either
90 ** a) "string" points to a null-terminated ASCII string, or
91 ** b) "string" points to a buffer containing a valid UTCTime,
92 ** whether null terminated or not, or
93 ** c) "string" contains at least 19 characters, with or without null char.
94 ** otherwise, this function may UMR and/or crash.
95 ** It suffices to ensure that the input "string" is at least 17 bytes long.
96 */
97 SECStatus
98 DER_AsciiToTime(PRTime *dst, const char *string)
99 {
100 return der_TimeStringToTime(dst, string, UTC_STRING, NULL);
101 }
102
103 SECStatus
104 DER_UTCTimeToTime(PRTime *dst, const SECItem *time)
105 {
106 /* Minimum valid UTCTime is yymmddhhmmZ which is 11 bytes.
107 ** Maximum valid UTCTime is yymmddhhmmss+0000 which is 17 bytes.
108 ** 20 should be large enough for all valid encoded times.
109 */
110 unsigned int i;
111 char localBuf[20];
112 const char *end = NULL;
113 SECStatus rv;
114
115 if (!time || !time->data || time->len < 11 || time->len > 17) {
116 PORT_SetError(SEC_ERROR_INVALID_TIME);
117 return SECFailure;
118 }
119
120 for (i = 0; i < time->len; i++) {
121 if (time->data[i] == '\0') {
122 PORT_SetError(SEC_ERROR_INVALID_TIME);
123 return SECFailure;
124 }
125 localBuf[i] = time->data[i];
126 }
127 localBuf[i] = '\0';
128
129 rv = der_TimeStringToTime(dst, localBuf, UTC_STRING, &end);
130 if (rv == SECSuccess && *end != '\0') {
131 PORT_SetError(SEC_ERROR_INVALID_TIME);
132 return SECFailure;
133 }
134 return rv;
135 }
136
137 /*
138 gmttime must contains UTC time in micro-seconds unit.
139 Note: the caller should make sure that Generalized time
140 should only be used for certifiate validities after the
141 year 2049. Otherwise, UTC time should be used. This routine
142 does not check this case, since it can be used to encode
143 certificate extension, which does not have this restriction.
144 */
145 SECStatus
146 DER_TimeToGeneralizedTimeArena(PLArenaPool* arenaOpt, SECItem *dst, PRTime gmttime)
147 {
148 PRExplodedTime printableTime;
149 unsigned char *d;
150
151 if ( (gmttime<January1st1) || (gmttime>=January1st10000) ) {
152 PORT_SetError(SEC_ERROR_INVALID_ARGS);
153 return SECFailure;
154 }
155 dst->len = 15;
156 if (arenaOpt) {
157 dst->data = d = (unsigned char*) PORT_ArenaAlloc(arenaOpt, dst->len);
158 } else {
159 dst->data = d = (unsigned char*) PORT_Alloc(dst->len);
160 }
161 dst->type = siGeneralizedTime;
162 if (!d) {
163 return SECFailure;
164 }
165
166 /* Convert a PRTime to a printable format. */
167 PR_ExplodeTime(gmttime, PR_GMTParameters, &printableTime);
168
169 /* The month in Generalized time is base one */
170 printableTime.tm_month++;
171
172 d[0] = (printableTime.tm_year /1000) + '0';
173 d[1] = ((printableTime.tm_year % 1000) / 100) + '0';
174 d[2] = ((printableTime.tm_year % 100) / 10) + '0';
175 d[3] = (printableTime.tm_year % 10) + '0';
176 d[4] = HIDIGIT(printableTime.tm_month);
177 d[5] = LODIGIT(printableTime.tm_month);
178 d[6] = HIDIGIT(printableTime.tm_mday);
179 d[7] = LODIGIT(printableTime.tm_mday);
180 d[8] = HIDIGIT(printableTime.tm_hour);
181 d[9] = LODIGIT(printableTime.tm_hour);
182 d[10] = HIDIGIT(printableTime.tm_min);
183 d[11] = LODIGIT(printableTime.tm_min);
184 d[12] = HIDIGIT(printableTime.tm_sec);
185 d[13] = LODIGIT(printableTime.tm_sec);
186 d[14] = 'Z';
187 return SECSuccess;
188 }
189
190 SECStatus
191 DER_TimeToGeneralizedTime(SECItem *dst, PRTime gmttime)
192 {
193 return DER_TimeToGeneralizedTimeArena(NULL, dst, gmttime);
194 }
195
196
197 SECStatus
198 DER_GeneralizedTimeToTime(PRTime *dst, const SECItem *time)
199 {
200 /* Minimum valid GeneralizedTime is ccyymmddhhmmZ which is 13 bytes.
201 ** Maximum valid GeneralizedTime is ccyymmddhhmmss+0000 which is 19 bytes.
202 ** 20 should be large enough for all valid encoded times.
203 */
204 unsigned int i;
205 char localBuf[20];
206 const char *end = NULL;
207 SECStatus rv;
208
209 if (!time || !time->data || time->len < 13 || time->len > 19) {
210 PORT_SetError(SEC_ERROR_INVALID_TIME);
211 return SECFailure;
212 }
213
214 for (i = 0; i < time->len; i++) {
215 if (time->data[i] == '\0') {
216 PORT_SetError(SEC_ERROR_INVALID_TIME);
217 return SECFailure;
218 }
219 localBuf[i] = time->data[i];
220 }
221 localBuf[i] = '\0';
222
223 rv = der_TimeStringToTime(dst, localBuf, GEN_STRING, &end);
224 if (rv == SECSuccess && *end != '\0') {
225 PORT_SetError(SEC_ERROR_INVALID_TIME);
226 return SECFailure;
227 }
228 return rv;
229 }
230
231 static SECStatus
232 der_TimeStringToTime(PRTime *dst, const char *string, int generalized,
233 const char **endptr)
234 {
235 PRExplodedTime genTime;
236 long hourOff = 0, minOff = 0;
237 PRUint16 century;
238 char signum;
239
240 if (string == NULL || dst == NULL) {
241 PORT_SetError(SEC_ERROR_INVALID_ARGS);
242 return SECFailure;
243 }
244
245 /* Verify time is formatted properly and capture information */
246 memset(&genTime, 0, sizeof genTime);
247
248 if (generalized == UTC_STRING) {
249 CAPTURE(genTime.tm_year, string, loser);
250 century = (genTime.tm_year < 50) ? 20 : 19;
251 } else {
252 CAPTURE(century, string, loser);
253 CAPTURE(genTime.tm_year, string, loser);
254 }
255 genTime.tm_year += century * 100;
256
257 CAPTURE(genTime.tm_month, string, loser);
258 if ((genTime.tm_month == 0) || (genTime.tm_month > 12))
259 goto loser;
260
261 /* NSPR month base is 0 */
262 --genTime.tm_month;
263
264 CAPTURE(genTime.tm_mday, string, loser);
265 if ((genTime.tm_mday == 0) || (genTime.tm_mday > 31))
266 goto loser;
267
268 CAPTURE(genTime.tm_hour, string, loser);
269 if (genTime.tm_hour > 23)
270 goto loser;
271
272 CAPTURE(genTime.tm_min, string, loser);
273 if (genTime.tm_min > 59)
274 goto loser;
275
276 if (ISDIGIT(string[0])) {
277 CAPTURE(genTime.tm_sec, string, loser);
278 if (genTime.tm_sec > 59)
279 goto loser;
280 }
281 signum = *string++;
282 if (signum == '+' || signum == '-') {
283 CAPTURE(hourOff, string, loser);
284 if (hourOff > 23)
285 goto loser;
286 CAPTURE(minOff, string, loser);
287 if (minOff > 59)
288 goto loser;
289 if (signum == '-') {
290 hourOff = -hourOff;
291 minOff = -minOff;
292 }
293 } else if (signum != 'Z') {
294 goto loser;
295 }
296
297 if (endptr)
298 *endptr = string;
299
300 /* Convert the GMT offset to seconds and save it in genTime
301 * for the implode time call.
302 */
303 genTime.tm_params.tp_gmt_offset = (PRInt32)((hourOff * 60L + minOff) * 60L);
304 *dst = PR_ImplodeTime(&genTime);
305 return SECSuccess;
306
307 loser:
308 PORT_SetError(SEC_ERROR_INVALID_TIME);
309 return SECFailure;
310 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)