Coverage Report

Created: 2022-08-24 06:31

/src/libressl/crypto/asn1/a_time_tm.c
Line
Count
Source (jump to first uncovered line)
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
0
#define RFC5280 0
31
38.2k
#define GENTIME_LENGTH 15
32
32.9k
#define UTCTIME_LENGTH 13
33
34
int
35
ASN1_time_tm_cmp(struct tm *tm1, struct tm *tm2)
36
0
{
37
0
  if (tm1->tm_year < tm2->tm_year)
38
0
    return (-1);
39
0
  if (tm1->tm_year > tm2->tm_year)
40
0
    return (1);
41
0
  if (tm1->tm_mon < tm2->tm_mon)
42
0
    return (-1);
43
0
  if (tm1->tm_mon > tm2->tm_mon)
44
0
    return (1);
45
0
  if (tm1->tm_mday < tm2->tm_mday)
46
0
    return (-1);
47
0
  if (tm1->tm_mday > tm2->tm_mday)
48
0
    return (1);
49
0
  if (tm1->tm_hour < tm2->tm_hour)
50
0
    return (-1);
51
0
  if (tm1->tm_hour > tm2->tm_hour)
52
0
    return (1);
53
0
  if (tm1->tm_min < tm2->tm_min)
54
0
    return (-1);
55
0
  if (tm1->tm_min > tm2->tm_min)
56
0
    return (1);
57
0
  if (tm1->tm_sec < tm2->tm_sec)
58
0
    return (-1);
59
0
  if (tm1->tm_sec > tm2->tm_sec)
60
0
    return (1);
61
0
  return 0;
62
0
}
63
64
int
65
ASN1_time_tm_clamp_notafter(struct tm *tm)
66
13.0k
{
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
13.0k
  return 1;
78
13.0k
}
79
80
/* Convert time to GeneralizedTime, X.690, 11.7. */
81
ASN1_TIME *
82
tm_to_gentime(struct tm *tm, ASN1_TIME *atime)
83
5.30k
{
84
5.30k
  char *time_str = NULL;
85
5.30k
  int year;
86
87
5.30k
  year = tm->tm_year + 1900;
88
5.30k
  if (year < 0 || year > 9999) {
89
0
    ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
90
0
    goto err;
91
0
  }
92
93
5.30k
  if (asprintf(&time_str, "%04u%02u%02u%02u%02u%02uZ", year,
94
5.30k
      tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
95
5.30k
      tm->tm_sec) == -1) {
96
0
    time_str = NULL;
97
0
    ASN1error(ERR_R_MALLOC_FAILURE);
98
0
    goto err;
99
0
  }
100
101
5.30k
  if (atime == NULL)
102
0
    atime = ASN1_TIME_new();
103
5.30k
  if (atime == NULL) {
104
0
    ASN1error(ERR_R_MALLOC_FAILURE);
105
0
    goto err;
106
0
  }
107
108
5.30k
  free(atime->data);
109
5.30k
  atime->data = time_str;
110
5.30k
  atime->length = GENTIME_LENGTH;
111
5.30k
  atime->type = V_ASN1_GENERALIZEDTIME;
112
113
5.30k
  return (atime);
114
115
0
 err:
116
0
  free(time_str);
117
118
0
  return (NULL);
119
5.30k
}
120
121
/* Convert time to UTCTime, X.690, 11.8. */
122
ASN1_TIME *
123
tm_to_utctime(struct tm *tm, ASN1_TIME *atime)
124
0
{
125
0
  char *time_str = NULL;
126
127
0
  if (tm->tm_year >= 150 || tm->tm_year < 50) {
128
0
    ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
129
0
    goto err;
130
0
  }
131
132
0
  if (asprintf(&time_str, "%02u%02u%02u%02u%02u%02uZ",
133
0
      tm->tm_year % 100,  tm->tm_mon + 1, tm->tm_mday,
134
0
      tm->tm_hour, tm->tm_min, tm->tm_sec) == -1) {
135
0
    time_str = NULL;
136
0
    ASN1error(ERR_R_MALLOC_FAILURE);
137
0
    goto err;
138
0
  }
139
140
0
  if (atime == NULL)
141
0
    atime = ASN1_TIME_new();
142
0
  if (atime == NULL) {
143
0
    ASN1error(ERR_R_MALLOC_FAILURE);
144
0
    goto err;
145
0
  }
146
147
0
  free(atime->data);
148
0
  atime->data = time_str;
149
0
  atime->length = UTCTIME_LENGTH;
150
0
  atime->type = V_ASN1_UTCTIME;
151
152
0
  return (atime);
153
154
0
 err:
155
0
  free(time_str);
156
157
0
  return (NULL);
158
0
}
159
160
ASN1_TIME *
161
tm_to_rfc5280_time(struct tm *tm, ASN1_TIME *atime)
162
0
{
163
0
  int year;
164
165
0
  year = tm->tm_year + 1900;
166
0
  if (year < 1950 || year > 9999) {
167
0
    ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
168
0
    return (NULL);
169
0
  }
170
171
0
  if (year < 2050)
172
0
    return (tm_to_utctime(tm, atime));
173
174
0
  return (tm_to_gentime(tm, atime));
175
0
}
176
177
178
static int
179
cbs_get_two_digit_value(CBS *cbs, int *out)
180
1.58M
{
181
1.58M
  uint8_t first_digit, second_digit;
182
183
1.58M
  if (!CBS_get_u8(cbs, &first_digit))
184
696
    return 0;
185
1.58M
  if (!isdigit(first_digit))
186
34.7k
    return 0;
187
1.54M
  if (!CBS_get_u8(cbs, &second_digit))
188
379
    return 0;
189
1.54M
  if (!isdigit(second_digit))
190
32.7k
    return 0;
191
192
1.51M
  *out = (first_digit - '0') * 10 + (second_digit - '0');
193
194
1.51M
  return 1;
195
1.54M
}
196
197
static int
198
is_valid_day(int year, int month, int day)
199
232k
{
200
232k
  if (day < 1)
201
37
    return 0;
202
232k
  switch (month) {
203
31.9k
  case 1:
204
74.1k
  case 3:
205
77.1k
  case 5:
206
93.3k
  case 7:
207
100k
  case 8:
208
114k
  case 10:
209
150k
  case 12:
210
150k
    return day <= 31;
211
13.1k
  case 4:
212
23.3k
  case 6:
213
27.6k
  case 9:
214
75.6k
  case 11:
215
75.6k
    return day <= 30;
216
6.48k
  case 2:
217
6.48k
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
218
2.51k
      return day <= 29;
219
3.96k
     else
220
3.96k
      return day <= 28;
221
0
  default:
222
0
    return 0;
223
232k
  }
224
232k
}
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
235
asn1_time_parse_cbs(const CBS *cbs, int is_gentime, struct tm *out_tm)
236
292k
{
237
292k
  int year, month, day, hour, min, sec, val;
238
292k
  CBS copy;
239
292k
  uint8_t tz;
240
241
292k
  CBS_dup(cbs, &copy);
242
243
292k
  if (is_gentime) {
244
103k
    if (!cbs_get_two_digit_value(&copy, &val))
245
8.34k
      return 0;
246
94.8k
    year = val * 100;
247
94.8k
    if (!cbs_get_two_digit_value(&copy, &val))
248
9.54k
      return 0;
249
85.3k
    year += val;
250
189k
  } else {
251
189k
    year = 1900;
252
189k
    if (!cbs_get_two_digit_value(&copy, &val))
253
1.71k
      return 0;
254
187k
    year += val;
255
187k
    if (year < 1950)
256
185k
      year += 100;
257
187k
    if (year >= 2050)
258
0
      return 0;  /* A Generalized time must be used. */
259
187k
  }
260
261
272k
  if (!cbs_get_two_digit_value(&copy, &month))
262
10.5k
    return 0;
263
262k
  if (month < 1 || month > 12)
264
20.7k
    return 0; /* Reject invalid months. */
265
266
241k
  if (!cbs_get_two_digit_value(&copy, &day))
267
8.47k
    return 0;
268
232k
  if (!is_valid_day(year, month, day))
269
1.74k
    return 0; /* Reject invalid days. */
270
271
231k
  if (!cbs_get_two_digit_value(&copy, &hour))
272
5.44k
    return 0;
273
225k
  if (hour > 23)
274
932
    return 0; /* Reject invalid hours. */
275
276
224k
  if (!cbs_get_two_digit_value(&copy, &min))
277
676
    return 0;
278
224k
  if (min > 59)
279
120
    return 0; /* Reject invalid minutes. */
280
281
224k
  if (!cbs_get_two_digit_value(&copy, &sec))
282
23.8k
    return 0;
283
200k
  if (sec > 59)
284
142
    return 0; /* Reject invalid seconds. Leap seconds are invalid. */
285
286
200k
  if (!CBS_get_u8(&copy, &tz))
287
69
    return 0;
288
200k
  if (tz != 'Z')
289
718
    return 0; /* Reject anything but Z on the end. */
290
291
199k
  if (CBS_len(&copy) != 0)
292
65
    return 0;  /* Reject invalid lengths. */
293
294
199k
  if (out_tm != NULL) {
295
31.4k
    memset(out_tm, 0, sizeof(*out_tm));
296
    /* Fill in the tm fields corresponding to what we validated. */
297
31.4k
    out_tm->tm_year = year - 1900;
298
31.4k
    out_tm->tm_mon = month - 1;
299
31.4k
    out_tm->tm_mday = day;
300
31.4k
    out_tm->tm_hour = hour;
301
31.4k
    out_tm->tm_min = min;
302
31.4k
    out_tm->tm_sec = sec;
303
31.4k
  }
304
305
199k
  return 1;
306
199k
}
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
324
ASN1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode)
325
32.9k
{
326
32.9k
  struct tm tml, *tmp = tm ? tm : &tml;
327
32.9k
  int type = 0;
328
32.9k
  CBS cbs;
329
330
32.9k
  if (bytes == NULL)
331
0
    return (-1);
332
333
32.9k
  CBS_init(&cbs, bytes, len);
334
335
32.9k
  if (CBS_len(&cbs) == UTCTIME_LENGTH)
336
26.1k
    type = V_ASN1_UTCTIME;
337
32.9k
  if (CBS_len(&cbs) == GENTIME_LENGTH)
338
5.30k
    type = V_ASN1_GENERALIZEDTIME;
339
32.9k
  if (asn1_time_parse_cbs(&cbs, type == V_ASN1_GENERALIZEDTIME, tmp)) {
340
31.4k
    if (mode != 0 && mode != type)
341
0
      return -1;
342
31.4k
    return type;
343
31.4k
  }
344
345
1.47k
  return -1;
346
32.9k
}
347
348
/*
349
 * ASN1_TIME generic functions.
350
 */
351
352
static int
353
ASN1_TIME_set_string_internal(ASN1_TIME *s, const char *str, int mode)
354
6.78k
{
355
6.78k
  int type;
356
6.78k
  char *tmp;
357
358
6.78k
  if ((type = ASN1_time_parse(str, strlen(str), NULL, mode)) == -1)
359
1.47k
    return (0);
360
5.30k
  if (mode != 0 && mode != type)
361
0
    return (0);
362
363
5.30k
  if (s == NULL)
364
0
    return (1);
365
366
5.30k
  if ((tmp = strdup(str)) == NULL)
367
0
    return (0);
368
5.30k
  free(s->data);
369
5.30k
  s->data = tmp;
370
5.30k
  s->length = strlen(tmp);
371
5.30k
  s->type = type;
372
373
5.30k
  return (1);
374
5.30k
}
375
376
static ASN1_TIME *
377
ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
378
    int mode)
379
6.78k
{
380
6.78k
  struct tm tm;
381
382
6.78k
  if (gmtime_r(&t, &tm) == NULL)
383
0
    return (NULL);
384
385
6.78k
  if (offset_day != 0 || offset_sec != 0) {
386
3.54k
    if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec))
387
1.47k
      return (NULL);
388
3.54k
  }
389
390
5.30k
  switch (mode) {
391
0
  case V_ASN1_UTCTIME:
392
0
    return (tm_to_utctime(&tm, s));
393
5.30k
  case V_ASN1_GENERALIZEDTIME:
394
5.30k
    return (tm_to_gentime(&tm, s));
395
0
  case RFC5280:
396
0
    return (tm_to_rfc5280_time(&tm, s));
397
0
  default:
398
0
    return (NULL);
399
5.30k
  }
400
5.30k
}
401
402
ASN1_TIME *
403
ASN1_TIME_set(ASN1_TIME *s, time_t t)
404
0
{
405
0
  return (ASN1_TIME_adj(s, t, 0, 0));
406
0
}
407
408
ASN1_TIME *
409
ASN1_TIME_set_tm(ASN1_TIME *s, struct tm *tm)
410
0
{
411
0
  time_t t;
412
413
0
  if ((t = timegm(tm)) == -1)
414
0
    return NULL;
415
0
  return (ASN1_TIME_adj(s, t, 0, 0));
416
0
}
417
418
ASN1_TIME *
419
ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec)
420
0
{
421
0
  return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, RFC5280));
422
0
}
423
424
int
425
ASN1_TIME_check(const ASN1_TIME *t)
426
0
{
427
0
  if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
428
0
    return (0);
429
0
  return (t->type == ASN1_time_parse(t->data, t->length, NULL, t->type));
430
0
}
431
432
ASN1_GENERALIZEDTIME *
433
ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
434
0
{
435
0
  ASN1_GENERALIZEDTIME *agt = NULL;
436
0
  struct tm tm;
437
438
0
  if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
439
0
    return (NULL);
440
441
0
  if (t->type != ASN1_time_parse(t->data, t->length, &tm, t->type))
442
0
    return (NULL);
443
444
0
  if (out != NULL)
445
0
    agt = *out;
446
0
  if ((agt = tm_to_gentime(&tm, agt)) == NULL)
447
0
    return (NULL);
448
0
  if (out != NULL)
449
0
    *out = agt;
450
451
0
  return (agt);
452
0
}
453
454
int
455
ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
456
0
{
457
0
  return (ASN1_TIME_set_string_internal(s, str, 0));
458
0
}
459
460
static int
461
ASN1_TIME_cmp_time_t_internal(const ASN1_TIME *s, time_t t2, int mode)
462
0
{
463
0
  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
0
  if (ASN1_time_parse(s->data, s->length, &tm1, mode) == -1)
476
0
    return -2;
477
478
0
  if (gmtime_r(&t2, &tm2) == NULL)
479
0
    return -2;
480
481
0
  return ASN1_time_tm_cmp(&tm1, &tm2);
482
0
}
483
484
int
485
ASN1_TIME_compare(const ASN1_TIME *t1, const ASN1_TIME *t2)
486
0
{
487
0
  struct tm tm1, tm2;
488
489
0
  if (t1->type != V_ASN1_UTCTIME && t1->type != V_ASN1_GENERALIZEDTIME)
490
0
    return -2;
491
492
0
  if (t2->type != V_ASN1_UTCTIME && t2->type != V_ASN1_GENERALIZEDTIME)
493
0
    return -2;
494
495
0
  if (ASN1_time_parse(t1->data, t1->length, &tm1, t1->type) == -1)
496
0
    return -2;
497
498
0
  if (ASN1_time_parse(t1->data, t2->length, &tm2, t2->type) == -1)
499
0
    return -2;
500
501
0
  return ASN1_time_tm_cmp(&tm1, &tm2);
502
0
}
503
504
int
505
ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
506
0
{
507
0
  if (s->type == V_ASN1_UTCTIME)
508
0
    return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
509
0
  if (s->type == V_ASN1_GENERALIZEDTIME)
510
0
    return ASN1_TIME_cmp_time_t_internal(s, t,
511
0
        V_ASN1_GENERALIZEDTIME);
512
0
  return -2;
513
0
}
514
515
/*
516
 * ASN1_UTCTIME wrappers
517
 */
518
519
int
520
ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
521
0
{
522
0
  if (d->type != V_ASN1_UTCTIME)
523
0
    return (0);
524
0
  return (d->type == ASN1_time_parse(d->data, d->length, NULL, d->type));
525
0
}
526
527
int
528
ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
529
0
{
530
0
  if (s != NULL && s->type != V_ASN1_UTCTIME)
531
0
    return (0);
532
0
  return (ASN1_TIME_set_string_internal(s, str, V_ASN1_UTCTIME));
533
0
}
534
535
ASN1_UTCTIME *
536
ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
537
0
{
538
0
  return (ASN1_UTCTIME_adj(s, t, 0, 0));
539
0
}
540
541
ASN1_UTCTIME *
542
ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec)
543
0
{
544
0
  return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
545
0
      V_ASN1_UTCTIME));
546
0
}
547
548
int
549
ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
550
0
{
551
0
  if (s->type == V_ASN1_UTCTIME)
552
0
    return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
553
0
  return -2;
554
0
}
555
556
/*
557
 * ASN1_GENERALIZEDTIME wrappers
558
 */
559
560
int
561
ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
562
0
{
563
0
  if (d->type != V_ASN1_GENERALIZEDTIME)
564
0
    return (0);
565
0
  return (d->type == ASN1_time_parse(d->data, d->length, NULL, d->type));
566
0
}
567
568
int
569
ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
570
6.78k
{
571
6.78k
  if (s != NULL && s->type != V_ASN1_GENERALIZEDTIME)
572
0
    return (0);
573
6.78k
  return (ASN1_TIME_set_string_internal(s, str, V_ASN1_GENERALIZEDTIME));
574
6.78k
}
575
576
ASN1_GENERALIZEDTIME *
577
ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t)
578
0
{
579
0
  return (ASN1_GENERALIZEDTIME_adj(s, t, 0, 0));
580
0
}
581
582
ASN1_GENERALIZEDTIME *
583
ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day,
584
    long offset_sec)
585
6.78k
{
586
6.78k
  return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
587
6.78k
      V_ASN1_GENERALIZEDTIME));
588
6.78k
}
589
590
int
591
ASN1_TIME_normalize(ASN1_TIME *t)
592
0
{
593
0
  struct tm tm;
594
595
0
  if (!ASN1_TIME_to_tm(t, &tm))
596
0
    return 0;
597
0
  return tm_to_rfc5280_time(&tm, t) != NULL;
598
0
}
599
600
int
601
ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
602
0
{
603
0
  return ASN1_TIME_set_string_internal(s, str, RFC5280);
604
0
}