xref: /dragonfly/crypto/libressl/crypto/asn1/a_time_tm.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1 /* $OpenBSD: a_time_tm.c,v 1.24 2022/07/04 14:39:43 tb 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 
18 #include <ctype.h>
19 #include <limits.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <time.h>
23 
24 #include <openssl/asn1t.h>
25 #include <openssl/err.h>
26 
27 #include "bytestring.h"
28 #include "o_time.h"
29 
30 #define RFC5280 0
31 #define GENTIME_LENGTH 15
32 #define UTCTIME_LENGTH 13
33 
34 int
ASN1_time_tm_cmp(struct tm * tm1,struct tm * tm2)35 ASN1_time_tm_cmp(struct tm *tm1, struct tm *tm2)
36 {
37           if (tm1->tm_year < tm2->tm_year)
38                     return (-1);
39           if (tm1->tm_year > tm2->tm_year)
40                     return (1);
41           if (tm1->tm_mon < tm2->tm_mon)
42                     return (-1);
43           if (tm1->tm_mon > tm2->tm_mon)
44                     return (1);
45           if (tm1->tm_mday < tm2->tm_mday)
46                     return (-1);
47           if (tm1->tm_mday > tm2->tm_mday)
48                     return (1);
49           if (tm1->tm_hour < tm2->tm_hour)
50                     return (-1);
51           if (tm1->tm_hour > tm2->tm_hour)
52                     return (1);
53           if (tm1->tm_min < tm2->tm_min)
54                     return (-1);
55           if (tm1->tm_min > tm2->tm_min)
56                     return (1);
57           if (tm1->tm_sec < tm2->tm_sec)
58                     return (-1);
59           if (tm1->tm_sec > tm2->tm_sec)
60                     return (1);
61           return 0;
62 }
63 
64 int
ASN1_time_tm_clamp_notafter(struct tm * tm)65 ASN1_time_tm_clamp_notafter(struct tm *tm)
66 {
67 #ifdef SMALL_TIME_T
68           struct tm broken_os_epoch_tm;
69           time_t broken_os_epoch_time = INT_MAX;
70 
71           if (gmtime_r(&broken_os_epoch_time, &broken_os_epoch_tm) == NULL)
72                     return 0;
73 
74           if (ASN1_time_tm_cmp(tm, &broken_os_epoch_tm) == 1)
75                     memcpy(tm, &broken_os_epoch_tm, sizeof(*tm));
76 #endif
77           return 1;
78 }
79 
80 /* Convert time to GeneralizedTime, X.690, 11.7. */
81 ASN1_TIME *
tm_to_gentime(struct tm * tm,ASN1_TIME * atime)82 tm_to_gentime(struct tm *tm, ASN1_TIME *atime)
83 {
84           char *time_str = NULL;
85           int year;
86 
87           year = tm->tm_year + 1900;
88           if (year < 0 || year > 9999) {
89                     ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
90                     goto err;
91           }
92 
93           if (asprintf(&time_str, "%04u%02u%02u%02u%02u%02uZ", year,
94               tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
95               tm->tm_sec) == -1) {
96                     time_str = NULL;
97                     ASN1error(ERR_R_MALLOC_FAILURE);
98                     goto err;
99           }
100 
101           if (atime == NULL)
102                     atime = ASN1_TIME_new();
103           if (atime == NULL) {
104                     ASN1error(ERR_R_MALLOC_FAILURE);
105                     goto err;
106           }
107 
108           free(atime->data);
109           atime->data = time_str;
110           atime->length = GENTIME_LENGTH;
111           atime->type = V_ASN1_GENERALIZEDTIME;
112 
113           return (atime);
114 
115  err:
116           free(time_str);
117 
118           return (NULL);
119 }
120 
121 /* Convert time to UTCTime, X.690, 11.8. */
122 ASN1_TIME *
tm_to_utctime(struct tm * tm,ASN1_TIME * atime)123 tm_to_utctime(struct tm *tm, ASN1_TIME *atime)
124 {
125           char *time_str = NULL;
126 
127           if (tm->tm_year >= 150 || tm->tm_year < 50) {
128                     ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
129                     goto err;
130           }
131 
132           if (asprintf(&time_str, "%02u%02u%02u%02u%02u%02uZ",
133               tm->tm_year % 100,  tm->tm_mon + 1, tm->tm_mday,
134               tm->tm_hour, tm->tm_min, tm->tm_sec) == -1) {
135                     time_str = NULL;
136                     ASN1error(ERR_R_MALLOC_FAILURE);
137                     goto err;
138           }
139 
140           if (atime == NULL)
141                     atime = ASN1_TIME_new();
142           if (atime == NULL) {
143                     ASN1error(ERR_R_MALLOC_FAILURE);
144                     goto err;
145           }
146 
147           free(atime->data);
148           atime->data = time_str;
149           atime->length = UTCTIME_LENGTH;
150           atime->type = V_ASN1_UTCTIME;
151 
152           return (atime);
153 
154  err:
155           free(time_str);
156 
157           return (NULL);
158 }
159 
160 ASN1_TIME *
tm_to_rfc5280_time(struct tm * tm,ASN1_TIME * atime)161 tm_to_rfc5280_time(struct tm *tm, ASN1_TIME *atime)
162 {
163           int year;
164 
165           year = tm->tm_year + 1900;
166           if (year < 1950 || year > 9999) {
167                     ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
168                     return (NULL);
169           }
170 
171           if (year < 2050)
172                     return (tm_to_utctime(tm, atime));
173 
174           return (tm_to_gentime(tm, atime));
175 }
176 
177 
178 static int
cbs_get_two_digit_value(CBS * cbs,int * out)179 cbs_get_two_digit_value(CBS *cbs, int *out)
180 {
181           uint8_t first_digit, second_digit;
182 
183           if (!CBS_get_u8(cbs, &first_digit))
184                     return 0;
185           if (!isdigit(first_digit))
186                     return 0;
187           if (!CBS_get_u8(cbs, &second_digit))
188                     return 0;
189           if (!isdigit(second_digit))
190                     return 0;
191 
192           *out = (first_digit - '0') * 10 + (second_digit - '0');
193 
194           return 1;
195 }
196 
197 static int
is_valid_day(int year,int month,int day)198 is_valid_day(int year, int month, int day)
199 {
200           if (day < 1)
201                     return 0;
202           switch (month) {
203           case 1:
204           case 3:
205           case 5:
206           case 7:
207           case 8:
208           case 10:
209           case 12:
210                     return day <= 31;
211           case 4:
212           case 6:
213           case 9:
214           case 11:
215                     return day <= 30;
216           case 2:
217                     if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
218                               return day <= 29;
219                      else
220                               return day <= 28;
221           default:
222                     return 0;
223           }
224 }
225 
226 /*
227  * asn1_time_parse_cbs returns one if |cbs| is a valid DER-encoded, ASN.1 Time
228  * body within the limitations imposed by RFC 5280, or zero otherwise. The time
229  * is expected to parse as a Generalized Time if is_gentime is true, and as a
230  * UTC Time otherwise. If |out_tm| is non-NULL, |*out_tm| will be zeroed, and
231  * then set to the corresponding time in UTC. This function does not compute
232  * |out_tm->tm_wday| or |out_tm->tm_yday|. |cbs| is not consumed.
233  */
234 int
asn1_time_parse_cbs(const CBS * cbs,int is_gentime,struct tm * out_tm)235 asn1_time_parse_cbs(const CBS *cbs, int is_gentime, struct tm *out_tm)
236 {
237           int year, month, day, hour, min, sec, val;
238           CBS copy;
239           uint8_t tz;
240 
241           CBS_dup(cbs, &copy);
242 
243           if (is_gentime) {
244                     if (!cbs_get_two_digit_value(&copy, &val))
245                               return 0;
246                     year = val * 100;
247                     if (!cbs_get_two_digit_value(&copy, &val))
248                               return 0;
249                     year += val;
250           } else {
251                     year = 1900;
252                     if (!cbs_get_two_digit_value(&copy, &val))
253                               return 0;
254                     year += val;
255                     if (year < 1950)
256                               year += 100;
257                     if (year >= 2050)
258                               return 0;  /* A Generalized time must be used. */
259           }
260 
261           if (!cbs_get_two_digit_value(&copy, &month))
262                     return 0;
263           if (month < 1 || month > 12)
264                     return 0; /* Reject invalid months. */
265 
266           if (!cbs_get_two_digit_value(&copy, &day))
267                     return 0;
268           if (!is_valid_day(year, month, day))
269                     return 0; /* Reject invalid days. */
270 
271           if (!cbs_get_two_digit_value(&copy, &hour))
272                     return 0;
273           if (hour > 23)
274                     return 0; /* Reject invalid hours. */
275 
276           if (!cbs_get_two_digit_value(&copy, &min))
277                     return 0;
278           if (min > 59)
279                     return 0; /* Reject invalid minutes. */
280 
281           if (!cbs_get_two_digit_value(&copy, &sec))
282                     return 0;
283           if (sec > 59)
284                     return 0; /* Reject invalid seconds. Leap seconds are invalid. */
285 
286           if (!CBS_get_u8(&copy, &tz))
287                     return 0;
288           if (tz != 'Z')
289                     return 0; /* Reject anything but Z on the end. */
290 
291           if (CBS_len(&copy) != 0)
292                     return 0;  /* Reject invalid lengths. */
293 
294           if (out_tm != NULL) {
295                     memset(out_tm, 0, sizeof(*out_tm));
296                     /* Fill in the tm fields corresponding to what we validated. */
297                     out_tm->tm_year = year - 1900;
298                     out_tm->tm_mon = month - 1;
299                     out_tm->tm_mday = day;
300                     out_tm->tm_hour = hour;
301                     out_tm->tm_min = min;
302                     out_tm->tm_sec = sec;
303           }
304 
305           return 1;
306 }
307 
308 /*
309  * Parse an RFC 5280 format ASN.1 time string.
310  *
311  * mode must be:
312  * 0 if we expect to parse a time as specified in RFC 5280 for an X509 object.
313  * V_ASN1_UTCTIME if we wish to parse an RFC5280 format UTC time.
314  * V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time.
315  *
316  * Returns:
317  * -1 if the string was invalid.
318  * V_ASN1_UTCTIME if the string validated as a UTC time string.
319  * V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string.
320  *
321  * Fills in *tm with the corresponding time if tm is non NULL.
322  */
323 int
ASN1_time_parse(const char * bytes,size_t len,struct tm * tm,int mode)324 ASN1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode)
325 {
326           struct tm tml, *tmp = tm ? tm : &tml;
327           int type = 0;
328           CBS cbs;
329 
330           if (bytes == NULL)
331                     return (-1);
332 
333           CBS_init(&cbs, bytes, len);
334 
335           if (CBS_len(&cbs) == UTCTIME_LENGTH)
336                     type = V_ASN1_UTCTIME;
337           if (CBS_len(&cbs) == GENTIME_LENGTH)
338                     type = V_ASN1_GENERALIZEDTIME;
339           if (asn1_time_parse_cbs(&cbs, type == V_ASN1_GENERALIZEDTIME, tmp)) {
340                     if (mode != 0 && mode != type)
341                               return -1;
342                     return type;
343           }
344 
345           return -1;
346 }
347 
348 /*
349  * ASN1_TIME generic functions.
350  */
351 
352 static int
ASN1_TIME_set_string_internal(ASN1_TIME * s,const char * str,int mode)353 ASN1_TIME_set_string_internal(ASN1_TIME *s, const char *str, int mode)
354 {
355           int type;
356           char *tmp;
357 
358           if ((type = ASN1_time_parse(str, strlen(str), NULL, mode)) == -1)
359                     return (0);
360           if (mode != 0 && mode != type)
361                     return (0);
362 
363           if (s == NULL)
364                     return (1);
365 
366           if ((tmp = strdup(str)) == NULL)
367                     return (0);
368           free(s->data);
369           s->data = tmp;
370           s->length = strlen(tmp);
371           s->type = type;
372 
373           return (1);
374 }
375 
376 static ASN1_TIME *
ASN1_TIME_adj_internal(ASN1_TIME * s,time_t t,int offset_day,long offset_sec,int mode)377 ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
378     int mode)
379 {
380           struct tm tm;
381 
382           if (gmtime_r(&t, &tm) == NULL)
383                     return (NULL);
384 
385           if (offset_day != 0 || offset_sec != 0) {
386                     if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec))
387                               return (NULL);
388           }
389 
390           switch (mode) {
391           case V_ASN1_UTCTIME:
392                     return (tm_to_utctime(&tm, s));
393           case V_ASN1_GENERALIZEDTIME:
394                     return (tm_to_gentime(&tm, s));
395           case RFC5280:
396                     return (tm_to_rfc5280_time(&tm, s));
397           default:
398                     return (NULL);
399           }
400 }
401 
402 ASN1_TIME *
ASN1_TIME_set(ASN1_TIME * s,time_t t)403 ASN1_TIME_set(ASN1_TIME *s, time_t t)
404 {
405           return (ASN1_TIME_adj(s, t, 0, 0));
406 }
407 
408 ASN1_TIME *
ASN1_TIME_set_tm(ASN1_TIME * s,struct tm * tm)409 ASN1_TIME_set_tm(ASN1_TIME *s, struct tm *tm)
410 {
411           time_t t;
412 
413           if ((t = timegm(tm)) == -1)
414                     return NULL;
415           return (ASN1_TIME_adj(s, t, 0, 0));
416 }
417 
418 ASN1_TIME *
ASN1_TIME_adj(ASN1_TIME * s,time_t t,int offset_day,long offset_sec)419 ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec)
420 {
421           return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, RFC5280));
422 }
423 
424 int
ASN1_TIME_check(const ASN1_TIME * t)425 ASN1_TIME_check(const ASN1_TIME *t)
426 {
427           if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
428                     return (0);
429           return (t->type == ASN1_time_parse(t->data, t->length, NULL, t->type));
430 }
431 
432 ASN1_GENERALIZEDTIME *
ASN1_TIME_to_generalizedtime(const ASN1_TIME * t,ASN1_GENERALIZEDTIME ** out)433 ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
434 {
435           ASN1_GENERALIZEDTIME *agt = NULL;
436           struct tm tm;
437 
438           if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
439                     return (NULL);
440 
441           if (t->type != ASN1_time_parse(t->data, t->length, &tm, t->type))
442                     return (NULL);
443 
444           if (out != NULL)
445                     agt = *out;
446           if ((agt = tm_to_gentime(&tm, agt)) == NULL)
447                     return (NULL);
448           if (out != NULL)
449                     *out = agt;
450 
451           return (agt);
452 }
453 
454 int
ASN1_TIME_set_string(ASN1_TIME * s,const char * str)455 ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
456 {
457           return (ASN1_TIME_set_string_internal(s, str, 0));
458 }
459 
460 static int
ASN1_TIME_cmp_time_t_internal(const ASN1_TIME * s,time_t t2,int mode)461 ASN1_TIME_cmp_time_t_internal(const ASN1_TIME *s, time_t t2, int mode)
462 {
463           struct tm tm1, tm2;
464 
465           /*
466            * This function has never handled failure conditions properly
467            * The OpenSSL version used to simply follow NULL pointers on failure.
468            * BoringSSL and OpenSSL now make it return -2 on failure.
469            *
470            * The danger is that users of this function will not differentiate the
471            * -2 failure case from s < t2. Callers must be careful. Sadly this is
472            * one of those pervasive things from OpenSSL we must continue with.
473            */
474 
475           if (ASN1_time_parse(s->data, s->length, &tm1, mode) == -1)
476                     return -2;
477 
478           if (gmtime_r(&t2, &tm2) == NULL)
479                     return -2;
480 
481           return ASN1_time_tm_cmp(&tm1, &tm2);
482 }
483 
484 int
ASN1_TIME_compare(const ASN1_TIME * t1,const ASN1_TIME * t2)485 ASN1_TIME_compare(const ASN1_TIME *t1, const ASN1_TIME *t2)
486 {
487           struct tm tm1, tm2;
488 
489           if (t1->type != V_ASN1_UTCTIME && t1->type != V_ASN1_GENERALIZEDTIME)
490                     return -2;
491 
492           if (t2->type != V_ASN1_UTCTIME && t2->type != V_ASN1_GENERALIZEDTIME)
493                     return -2;
494 
495           if (ASN1_time_parse(t1->data, t1->length, &tm1, t1->type) == -1)
496                     return -2;
497 
498           if (ASN1_time_parse(t1->data, t2->length, &tm2, t2->type) == -1)
499                     return -2;
500 
501           return ASN1_time_tm_cmp(&tm1, &tm2);
502 }
503 
504 int
ASN1_TIME_cmp_time_t(const ASN1_TIME * s,time_t t)505 ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
506 {
507           if (s->type == V_ASN1_UTCTIME)
508                     return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
509           if (s->type == V_ASN1_GENERALIZEDTIME)
510                     return ASN1_TIME_cmp_time_t_internal(s, t,
511                         V_ASN1_GENERALIZEDTIME);
512           return -2;
513 }
514 
515 /*
516  * ASN1_UTCTIME wrappers
517  */
518 
519 int
ASN1_UTCTIME_check(const ASN1_UTCTIME * d)520 ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
521 {
522           if (d->type != V_ASN1_UTCTIME)
523                     return (0);
524           return (d->type == ASN1_time_parse(d->data, d->length, NULL, d->type));
525 }
526 
527 int
ASN1_UTCTIME_set_string(ASN1_UTCTIME * s,const char * str)528 ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
529 {
530           if (s != NULL && s->type != V_ASN1_UTCTIME)
531                     return (0);
532           return (ASN1_TIME_set_string_internal(s, str, V_ASN1_UTCTIME));
533 }
534 
535 ASN1_UTCTIME *
ASN1_UTCTIME_set(ASN1_UTCTIME * s,time_t t)536 ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
537 {
538           return (ASN1_UTCTIME_adj(s, t, 0, 0));
539 }
540 
541 ASN1_UTCTIME *
ASN1_UTCTIME_adj(ASN1_UTCTIME * s,time_t t,int offset_day,long offset_sec)542 ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec)
543 {
544           return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
545               V_ASN1_UTCTIME));
546 }
547 
548 int
ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME * s,time_t t)549 ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
550 {
551           if (s->type == V_ASN1_UTCTIME)
552                     return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
553           return -2;
554 }
555 
556 /*
557  * ASN1_GENERALIZEDTIME wrappers
558  */
559 
560 int
ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME * d)561 ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
562 {
563           if (d->type != V_ASN1_GENERALIZEDTIME)
564                     return (0);
565           return (d->type == ASN1_time_parse(d->data, d->length, NULL, d->type));
566 }
567 
568 int
ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME * s,const char * str)569 ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
570 {
571           if (s != NULL && s->type != V_ASN1_GENERALIZEDTIME)
572                     return (0);
573           return (ASN1_TIME_set_string_internal(s, str, V_ASN1_GENERALIZEDTIME));
574 }
575 
576 ASN1_GENERALIZEDTIME *
ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME * s,time_t t)577 ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t)
578 {
579           return (ASN1_GENERALIZEDTIME_adj(s, t, 0, 0));
580 }
581 
582 ASN1_GENERALIZEDTIME *
ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME * s,time_t t,int offset_day,long offset_sec)583 ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day,
584     long offset_sec)
585 {
586           return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
587               V_ASN1_GENERALIZEDTIME));
588 }
589 
590 int
ASN1_TIME_normalize(ASN1_TIME * t)591 ASN1_TIME_normalize(ASN1_TIME *t)
592 {
593           struct tm tm;
594 
595           if (!ASN1_TIME_to_tm(t, &tm))
596                     return 0;
597           return tm_to_rfc5280_time(&tm, t) != NULL;
598 }
599 
600 int
ASN1_TIME_set_string_X509(ASN1_TIME * s,const char * str)601 ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
602 {
603           return ASN1_TIME_set_string_internal(s, str, RFC5280);
604 }
605