diff options
Diffstat (limited to 'src/lib/libcrypto/asn1/a_time_tm.c')
-rw-r--r-- | src/lib/libcrypto/asn1/a_time_tm.c | 446 |
1 files changed, 0 insertions, 446 deletions
diff --git a/src/lib/libcrypto/asn1/a_time_tm.c b/src/lib/libcrypto/asn1/a_time_tm.c deleted file mode 100644 index aa3cb9994c..0000000000 --- a/src/lib/libcrypto/asn1/a_time_tm.c +++ /dev/null | |||
@@ -1,446 +0,0 @@ | |||
1 | /* $OpenBSD: a_time_tm.c,v 1.9 2015/12/12 21:02:59 beck Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2015 Bob Beck <beck@openbsd.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | #include <ctype.h> | ||
18 | #include <limits.h> | ||
19 | #include <stdio.h> | ||
20 | #include <string.h> | ||
21 | #include <time.h> | ||
22 | |||
23 | #include <openssl/asn1t.h> | ||
24 | #include <openssl/err.h> | ||
25 | |||
26 | #include "o_time.h" | ||
27 | |||
28 | #define RFC5280 0 | ||
29 | #define GENTIME_LENGTH 15 | ||
30 | #define UTCTIME_LENGTH 13 | ||
31 | |||
32 | int | ||
33 | asn1_tm_cmp(struct tm *tm1, struct tm *tm2) { | ||
34 | if (tm1->tm_year < tm2->tm_year) | ||
35 | return (-1); | ||
36 | if (tm1->tm_year > tm2->tm_year) | ||
37 | return (1); | ||
38 | if (tm1->tm_mon < tm2->tm_mon) | ||
39 | return (-1); | ||
40 | if (tm1->tm_mon > tm2->tm_mon) | ||
41 | return (1); | ||
42 | if (tm1->tm_mday < tm2->tm_mday) | ||
43 | return (-1); | ||
44 | if (tm1->tm_mday > tm2->tm_mday) | ||
45 | return (1); | ||
46 | if (tm1->tm_hour < tm2->tm_hour) | ||
47 | return (-1); | ||
48 | if (tm1->tm_hour > tm2->tm_hour) | ||
49 | return (1); | ||
50 | if (tm1->tm_min < tm2->tm_min) | ||
51 | return (-1); | ||
52 | if (tm1->tm_min > tm2->tm_min) | ||
53 | return (1); | ||
54 | if (tm1->tm_sec < tm2->tm_sec) | ||
55 | return (-1); | ||
56 | if (tm1->tm_sec > tm2->tm_sec) | ||
57 | return (1); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | /* Format a time as an RFC 5280 format Generalized time */ | ||
62 | char * | ||
63 | gentime_string_from_tm(struct tm *tm) | ||
64 | { | ||
65 | char *ret = NULL; | ||
66 | int year; | ||
67 | |||
68 | year = tm->tm_year + 1900; | ||
69 | if (year < 0 || year > 9999) | ||
70 | return (NULL); | ||
71 | |||
72 | if (asprintf(&ret, "%04u%02u%02u%02u%02u%02uZ", year, | ||
73 | tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
74 | tm->tm_sec) == -1) | ||
75 | ret = NULL; | ||
76 | |||
77 | return (ret); | ||
78 | } | ||
79 | |||
80 | /* Format a time as an RFC 5280 format UTC time */ | ||
81 | char * | ||
82 | utctime_string_from_tm(struct tm *tm) | ||
83 | { | ||
84 | char *ret = NULL; | ||
85 | |||
86 | if (tm->tm_year >= 150 || tm->tm_year < 50) | ||
87 | return (NULL); | ||
88 | |||
89 | if (asprintf(&ret, "%02u%02u%02u%02u%02u%02uZ", | ||
90 | tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, | ||
91 | tm->tm_hour, tm->tm_min, tm->tm_sec) == -1) | ||
92 | ret = NULL; | ||
93 | |||
94 | return (ret); | ||
95 | } | ||
96 | |||
97 | /* Format a time correctly for an X509 object as per RFC 5280 */ | ||
98 | char * | ||
99 | rfc5280_string_from_tm(struct tm *tm) | ||
100 | { | ||
101 | char *ret = NULL; | ||
102 | int year; | ||
103 | |||
104 | year = tm->tm_year + 1900; | ||
105 | if (year < 1950 || year > 9999) | ||
106 | return (NULL); | ||
107 | |||
108 | if (year < 2050) | ||
109 | ret = utctime_string_from_tm(tm); | ||
110 | else | ||
111 | ret = gentime_string_from_tm(tm); | ||
112 | |||
113 | return (ret); | ||
114 | } | ||
115 | |||
116 | /* | ||
117 | * Parse an RFC 5280 format ASN.1 time string. | ||
118 | * | ||
119 | * mode must be: | ||
120 | * 0 if we expect to parse a time as specified in RFC 5280 from an X509 object. | ||
121 | * V_ASN1_UTCTIME if we wish to parse on RFC5280 format UTC time. | ||
122 | * V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time. | ||
123 | * | ||
124 | * Returns: | ||
125 | * -1 if the string was invalid. | ||
126 | * V_ASN1_UTCTIME if the string validated as a UTC time string. | ||
127 | * V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string. | ||
128 | * | ||
129 | * Fills in *tm with the corresponding time if tm is non NULL. | ||
130 | */ | ||
131 | #define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0')) | ||
132 | int | ||
133 | asn1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode) | ||
134 | { | ||
135 | size_t i; | ||
136 | int type = 0; | ||
137 | struct tm ltm; | ||
138 | struct tm *lt; | ||
139 | const char *p; | ||
140 | |||
141 | if (bytes == NULL) | ||
142 | return (-1); | ||
143 | |||
144 | /* Constrain to valid lengths. */ | ||
145 | if (len != UTCTIME_LENGTH && len != GENTIME_LENGTH) | ||
146 | return (-1); | ||
147 | |||
148 | lt = tm; | ||
149 | if (lt == NULL) { | ||
150 | memset(<m, 0, sizeof(ltm)); | ||
151 | lt = <m; | ||
152 | } | ||
153 | |||
154 | /* Timezone is required and must be GMT (Zulu). */ | ||
155 | if (bytes[len - 1] != 'Z') | ||
156 | return (-1); | ||
157 | |||
158 | /* Make sure everything else is digits. */ | ||
159 | for (i = 0; i < len - 1; i++) { | ||
160 | if (isdigit((unsigned char)bytes[i])) | ||
161 | continue; | ||
162 | return (-1); | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Validate and convert the time | ||
167 | */ | ||
168 | p = bytes; | ||
169 | switch (len) { | ||
170 | case GENTIME_LENGTH: | ||
171 | if (mode == V_ASN1_UTCTIME) | ||
172 | return (-1); | ||
173 | lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ | ||
174 | type = V_ASN1_GENERALIZEDTIME; | ||
175 | /* FALLTHROUGH */ | ||
176 | case UTCTIME_LENGTH: | ||
177 | if (type == 0) { | ||
178 | if (mode == V_ASN1_GENERALIZEDTIME) | ||
179 | return (-1); | ||
180 | type = V_ASN1_UTCTIME; | ||
181 | } | ||
182 | lt->tm_year += ATOI2(p); /* yy */ | ||
183 | if (type == V_ASN1_UTCTIME) { | ||
184 | if (lt->tm_year < 50) | ||
185 | lt->tm_year += 100; | ||
186 | } | ||
187 | lt->tm_mon = ATOI2(p) - 1; /* mm */ | ||
188 | if (lt->tm_mon < 0 || lt->tm_mon > 11) | ||
189 | return (-1); | ||
190 | lt->tm_mday = ATOI2(p); /* dd */ | ||
191 | if (lt->tm_mday < 1 || lt->tm_mday > 31) | ||
192 | return (-1); | ||
193 | lt->tm_hour = ATOI2(p); /* HH */ | ||
194 | if (lt->tm_hour < 0 || lt->tm_hour > 23) | ||
195 | return (-1); | ||
196 | lt->tm_min = ATOI2(p); /* MM */ | ||
197 | if (lt->tm_min < 0 || lt->tm_min > 59) | ||
198 | return (-1); | ||
199 | lt->tm_sec = ATOI2(p); /* SS */ | ||
200 | /* Leap second 60 is not accepted. Reconsider later? */ | ||
201 | if (lt->tm_sec < 0 || lt->tm_sec > 59) | ||
202 | return (-1); | ||
203 | break; | ||
204 | default: | ||
205 | return (-1); | ||
206 | } | ||
207 | |||
208 | return (type); | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * ASN1_TIME generic functions. | ||
213 | */ | ||
214 | |||
215 | static int | ||
216 | ASN1_TIME_set_string_internal(ASN1_TIME *s, const char *str, int mode) | ||
217 | { | ||
218 | int type; | ||
219 | char *tmp; | ||
220 | |||
221 | if ((type = asn1_time_parse(str, strlen(str), NULL, mode)) == -1) | ||
222 | return (0); | ||
223 | if (mode != 0 && mode != type) | ||
224 | return (0); | ||
225 | |||
226 | if (s == NULL) | ||
227 | return (1); | ||
228 | |||
229 | if ((tmp = strdup(str)) == NULL) | ||
230 | return (0); | ||
231 | free(s->data); | ||
232 | s->data = tmp; | ||
233 | s->length = strlen(tmp); | ||
234 | s->type = type; | ||
235 | |||
236 | return (1); | ||
237 | } | ||
238 | |||
239 | static ASN1_TIME * | ||
240 | ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec, | ||
241 | int mode) | ||
242 | { | ||
243 | int allocated = 0; | ||
244 | struct tm tm; | ||
245 | size_t len; | ||
246 | char * p; | ||
247 | |||
248 | if (gmtime_r(&t, &tm) == NULL) | ||
249 | return (NULL); | ||
250 | |||
251 | if (offset_day || offset_sec) { | ||
252 | if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec)) | ||
253 | return (NULL); | ||
254 | } | ||
255 | |||
256 | switch (mode) { | ||
257 | case V_ASN1_UTCTIME: | ||
258 | p = utctime_string_from_tm(&tm); | ||
259 | break; | ||
260 | case V_ASN1_GENERALIZEDTIME: | ||
261 | p = gentime_string_from_tm(&tm); | ||
262 | break; | ||
263 | case RFC5280: | ||
264 | p = rfc5280_string_from_tm(&tm); | ||
265 | break; | ||
266 | default: | ||
267 | return (NULL); | ||
268 | } | ||
269 | if (p == NULL) { | ||
270 | ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, | ||
271 | ASN1_R_ILLEGAL_TIME_VALUE); | ||
272 | return (NULL); | ||
273 | } | ||
274 | |||
275 | if (s == NULL) { | ||
276 | if ((s = ASN1_TIME_new()) == NULL) | ||
277 | return (NULL); | ||
278 | allocated = 1; | ||
279 | } | ||
280 | |||
281 | len = strlen(p); | ||
282 | switch (len) { | ||
283 | case GENTIME_LENGTH: | ||
284 | s->type = V_ASN1_GENERALIZEDTIME; | ||
285 | break; | ||
286 | case UTCTIME_LENGTH: | ||
287 | s->type = V_ASN1_UTCTIME; | ||
288 | break; | ||
289 | default: | ||
290 | if (allocated) | ||
291 | ASN1_TIME_free(s); | ||
292 | free(p); | ||
293 | return (NULL); | ||
294 | } | ||
295 | free(s->data); | ||
296 | s->data = p; | ||
297 | s->length = len; | ||
298 | return (s); | ||
299 | } | ||
300 | |||
301 | ASN1_TIME * | ||
302 | ASN1_TIME_set(ASN1_TIME *s, time_t t) | ||
303 | { | ||
304 | return (ASN1_TIME_adj(s, t, 0, 0)); | ||
305 | } | ||
306 | |||
307 | ASN1_TIME * | ||
308 | ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec) | ||
309 | { | ||
310 | return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, RFC5280)); | ||
311 | } | ||
312 | |||
313 | int | ||
314 | ASN1_TIME_check(ASN1_TIME *t) | ||
315 | { | ||
316 | if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME) | ||
317 | return (0); | ||
318 | return (t->type == asn1_time_parse(t->data, t->length, NULL, t->type)); | ||
319 | } | ||
320 | |||
321 | ASN1_GENERALIZEDTIME * | ||
322 | ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) | ||
323 | { | ||
324 | ASN1_GENERALIZEDTIME *tmp = NULL; | ||
325 | struct tm tm; | ||
326 | char *str; | ||
327 | |||
328 | if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME) | ||
329 | return (NULL); | ||
330 | |||
331 | memset(&tm, 0, sizeof(tm)); | ||
332 | if (t->type != asn1_time_parse(t->data, t->length, &tm, t->type)) | ||
333 | return (NULL); | ||
334 | if ((str = gentime_string_from_tm(&tm)) == NULL) | ||
335 | return (NULL); | ||
336 | |||
337 | if (out != NULL) | ||
338 | tmp = *out; | ||
339 | if (tmp == NULL && (tmp = ASN1_GENERALIZEDTIME_new()) == NULL) { | ||
340 | free(str); | ||
341 | return (NULL); | ||
342 | } | ||
343 | if (out != NULL) | ||
344 | *out = tmp; | ||
345 | |||
346 | free(tmp->data); | ||
347 | tmp->data = str; | ||
348 | tmp->length = strlen(str); | ||
349 | return (tmp); | ||
350 | } | ||
351 | |||
352 | int | ||
353 | ASN1_TIME_set_string(ASN1_TIME *s, const char *str) | ||
354 | { | ||
355 | return (ASN1_TIME_set_string_internal(s, str, 0)); | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * ASN1_UTCTIME wrappers | ||
360 | */ | ||
361 | |||
362 | int | ||
363 | ASN1_UTCTIME_check(ASN1_UTCTIME *d) | ||
364 | { | ||
365 | if (d->type != V_ASN1_UTCTIME) | ||
366 | return (0); | ||
367 | return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); | ||
368 | } | ||
369 | |||
370 | int | ||
371 | ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) | ||
372 | { | ||
373 | if (s != NULL && s->type != V_ASN1_UTCTIME) | ||
374 | return (0); | ||
375 | return (ASN1_TIME_set_string_internal(s, str, V_ASN1_UTCTIME)); | ||
376 | } | ||
377 | |||
378 | ASN1_UTCTIME * | ||
379 | ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) | ||
380 | { | ||
381 | return (ASN1_UTCTIME_adj(s, t, 0, 0)); | ||
382 | } | ||
383 | |||
384 | ASN1_UTCTIME * | ||
385 | ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec) | ||
386 | { | ||
387 | return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, | ||
388 | V_ASN1_UTCTIME)); | ||
389 | } | ||
390 | |||
391 | int | ||
392 | ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t2) | ||
393 | { | ||
394 | struct tm tm1, tm2; | ||
395 | |||
396 | /* | ||
397 | * This function has never handled failure conditions properly | ||
398 | * and should be deprecated. The OpenSSL version used to | ||
399 | * simply follow NULL pointers on failure. BoringSSL and | ||
400 | * OpenSSL now make it return -2 on failure. | ||
401 | * | ||
402 | * The danger is that users of this function will not | ||
403 | * differentiate the -2 failure case from t1 < t2. | ||
404 | */ | ||
405 | if (asn1_time_parse(s->data, s->length, &tm1, V_ASN1_UTCTIME) == -1) | ||
406 | return (-2); /* XXX */ | ||
407 | |||
408 | if (gmtime_r(&t2, &tm2) == NULL) | ||
409 | return (-2); /* XXX */ | ||
410 | |||
411 | return asn1_tm_cmp(&tm1, &tm2); | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * ASN1_GENERALIZEDTIME wrappers | ||
416 | */ | ||
417 | |||
418 | int | ||
419 | ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d) | ||
420 | { | ||
421 | if (d->type != V_ASN1_GENERALIZEDTIME) | ||
422 | return (0); | ||
423 | return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); | ||
424 | } | ||
425 | |||
426 | int | ||
427 | ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) | ||
428 | { | ||
429 | if (s != NULL && s->type != V_ASN1_GENERALIZEDTIME) | ||
430 | return (0); | ||
431 | return (ASN1_TIME_set_string_internal(s, str, V_ASN1_GENERALIZEDTIME)); | ||
432 | } | ||
433 | |||
434 | ASN1_GENERALIZEDTIME * | ||
435 | ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t) | ||
436 | { | ||
437 | return (ASN1_GENERALIZEDTIME_adj(s, t, 0, 0)); | ||
438 | } | ||
439 | |||
440 | ASN1_GENERALIZEDTIME * | ||
441 | ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, | ||
442 | long offset_sec) | ||
443 | { | ||
444 | return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, | ||
445 | V_ASN1_GENERALIZEDTIME)); | ||
446 | } | ||