Coverage Report

Created: 2022-08-24 06:30

/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
0
#define GENTIME_LENGTH 15
32
0
#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
0
{
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
0
  return 1;
78
0
}
79
80
/* Convert time to GeneralizedTime, X.690, 11.7. */
81
ASN1_TIME *
82
tm_to_gentime(struct tm *tm, ASN1_TIME *atime)
83
0
{
84
0
  char *time_str = NULL;
85
0
  int year;
86
87
0
  year = tm->tm_year + 1900;
88
0
  if (year < 0 || year > 9999) {
89
0
    ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
90
0
    goto err;
91
0
  }
92
93
0
  if (asprintf(&time_str, "%04u%02u%02u%02u%02u%02uZ", year,
94
0
      tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
95
0
      tm->tm_sec) == -1) {
96
0
    time_str = NULL;
97
0
    ASN1error(ERR_R_MALLOC_FAILURE);
98
0
    goto err;
99
0
  }
100
101
0
  if (atime == NULL)
102
0
    atime = ASN1_TIME_new();
103
0
  if (atime == NULL) {
104
0
    ASN1error(ERR_R_MALLOC_FAILURE);
105
0
    goto err;
106
0
  }
107
108
0
  free(atime->data);
109
0
  atime->data = time_str;
110
0
  atime->length = GENTIME_LENGTH;
111
0
  atime->type = V_ASN1_GENERALIZEDTIME;
112
113
0
  return (atime);
114
115
0
 err:
116
0
  free(time_str);
117
118
0
  return (NULL);
119
0
}
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
0
{
181
0
  uint8_t first_digit, second_digit;
182
183
0
  if (!CBS_get_u8(cbs, &first_digit))
184
0
    return 0;
185
0
  if (!isdigit(first_digit))
186
0
    return 0;
187
0
  if (!CBS_get_u8(cbs, &second_digit))
188
0
    return 0;
189
0
  if (!isdigit(second_digit))
190
0
    return 0;
191
192
0
  *out = (first_digit - '0') * 10 + (second_digit - '0');
193
194
0
  return 1;
195
0
}
196
197
static int
198
is_valid_day(int year, int month, int day)
199
0
{
200
0
  if (day < 1)
201
0
    return 0;
202
0
  switch (month) {
203
0
  case 1:
204
0
  case 3:
205
0
  case 5:
206
0
  case 7:
207
0
  case 8:
208
0
  case 10:
209
0
  case 12:
210
0
    return day <= 31;
211
0
  case 4:
212
0
  case 6:
213
0
  case 9:
214
0
  case 11:
215
0
    return day <= 30;
216
0
  case 2:
217
0
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
218
0
      return day <= 29;
219
0
     else
220
0
      return day <= 28;
221
0
  default:
222
0
    return 0;
223
0
  }
224
0
}
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
0
{
237
0
  int year, month, day, hour, min, sec, val;
238
0
  CBS copy;
239
0
  uint8_t tz;
240
241
0
  CBS_dup(cbs, &copy);
242
243
0
  if (is_gentime) {
244
0
    if (!cbs_get_two_digit_value(&copy, &val))
245
0
      return 0;
246
0
    year = val * 100;
247
0
    if (!cbs_get_two_digit_value(&copy, &val))
248
0
      return 0;
249
0
    year += val;
250
0
  } else {
251
0
    year = 1900;
252
0
    if (!cbs_get_two_digit_value(&copy, &val))
253
0
      return 0;
254
0
    year += val;
255
0
    if (year < 1950)
256
0
      year += 100;
257
0
    if (year >= 2050)
258
0
      return 0;  /* A Generalized time must be used. */
259
0
  }
260
261
0
  if (!cbs_get_two_digit_value(&copy, &month))
262
0
    return 0;
263
0
  if (month < 1 || month > 12)
264
0
    return 0; /* Reject invalid months. */
265
266
0
  if (!cbs_get_two_digit_value(&copy, &day))
267
0
    return 0;
268
0
  if (!is_valid_day(year, month, day))
269
0
    return 0; /* Reject invalid days. */
270
271
0
  if (!cbs_get_two_digit_value(&copy, &hour))
272
0
    return 0;
273
0
  if (hour > 23)
274
0
    return 0; /* Reject invalid hours. */
275
276
0
  if (!cbs_get_two_digit_value(&copy, &min))
277
0
    return 0;
278
0
  if (min > 59)
279
0
    return 0; /* Reject invalid minutes. */
280
281
0
  if (!cbs_get_two_digit_value(&copy, &sec))
282
0
    return 0;
283
0
  if (sec > 59)
284
0
    return 0; /* Reject invalid seconds. Leap seconds are invalid. */
285
286
0
  if (!CBS_get_u8(&copy, &tz))
287
0
    return 0;
288
0
  if (tz != 'Z')
289
0
    return 0; /* Reject anything but Z on the end. */
290
291
0
  if (CBS_len(&copy) != 0)
292
0
    return 0;  /* Reject invalid lengths. */
293
294
0
  if (out_tm != NULL) {
295
0
    memset(out_tm, 0, sizeof(*out_tm));
296
    /* Fill in the tm fields corresponding to what we validated. */
297
0
    out_tm->tm_year = year - 1900;
298
0
    out_tm->tm_mon = month - 1;
299
0
    out_tm->tm_mday = day;
300
0
    out_tm->tm_hour = hour;
301
0
    out_tm->tm_min = min;
302
0
    out_tm->tm_sec = sec;
303
0
  }
304
305
0
  return 1;
306
0
}
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
0
{
326
0
  struct tm tml, *tmp = tm ? tm : &tml;
327
0
  int type = 0;
328
0
  CBS cbs;
329
330
0
  if (bytes == NULL)
331
0
    return (-1);
332
333
0
  CBS_init(&cbs, bytes, len);
334
335
0
  if (CBS_len(&cbs) == UTCTIME_LENGTH)
336
0
    type = V_ASN1_UTCTIME;
337
0
  if (CBS_len(&cbs) == GENTIME_LENGTH)
338
0
    type = V_ASN1_GENERALIZEDTIME;
339
0
  if (asn1_time_parse_cbs(&cbs, type == V_ASN1_GENERALIZEDTIME, tmp)) {
340
0
    if (mode != 0 && mode != type)
341
0
      return -1;
342
0
    return type;
343
0
  }
344
345
0
  return -1;
346
0
}
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
0
{
355
0
  int type;
356
0
  char *tmp;
357
358
0
  if ((type = ASN1_time_parse(str, strlen(str), NULL, mode)) == -1)
359
0
    return (0);
360
0
  if (mode != 0 && mode != type)
361
0
    return (0);
362
363
0
  if (s == NULL)
364
0
    return (1);
365
366
0
  if ((tmp = strdup(str)) == NULL)
367
0
    return (0);
368
0
  free(s->data);
369
0
  s->data = tmp;
370
0
  s->length = strlen(tmp);
371
0
  s->type = type;
372
373
0
  return (1);
374
0
}
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
0
{
380
0
  struct tm tm;
381
382
0
  if (gmtime_r(&t, &tm) == NULL)
383
0
    return (NULL);
384
385
0
  if (offset_day != 0 || offset_sec != 0) {
386
0
    if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec))
387
0
      return (NULL);
388
0
  }
389
390
0
  switch (mode) {
391
0
  case V_ASN1_UTCTIME:
392
0
    return (tm_to_utctime(&tm, s));
393
0
  case V_ASN1_GENERALIZEDTIME:
394
0
    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
0
  }
400
0
}
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
0
{
571
0
  if (s != NULL && s->type != V_ASN1_GENERALIZEDTIME)
572
0
    return (0);
573
0
  return (ASN1_TIME_set_string_internal(s, str, V_ASN1_GENERALIZEDTIME));
574
0
}
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
0
{
586
0
  return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
587
0
      V_ASN1_GENERALIZEDTIME));
588
0
}
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
}