Mercurial > trustbridge > nss-cmake-static
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 } |