1 /*
2 * Copyright (C) 2003-2016 Free Software Foundation, Inc.
3 * Copyright (C) 2016 Red Hat, Inc.
4 *
5 * Author: Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 *
22 */
23
24 #include "gnutls_int.h"
25 #include <libtasn1.h>
26 #include <datum.h>
27 #include <global.h>
28 #include "errors.h"
29 #include <str.h>
30 #include <x509.h>
31 #include <num.h>
32 #include <x509_b64.h>
33 #include "x509_int.h"
34 #include "extras/hex.h"
35 #include <common.h>
36 #include <c-ctype.h>
37
38 time_t _gnutls_utcTime2gtime(const char *ttime);
39
40 /* TIME functions
41 * Conversions between generalized or UTC time to time_t
42 *
43 */
44
45 /* This is an emulation of the struct tm.
46 * Since we do not use libc's functions, we don't need to
47 * depend on the libc structure.
48 */
49 typedef struct fake_tm {
50 int tm_mon;
51 int tm_year; /* FULL year - ie 1971 */
52 int tm_mday;
53 int tm_hour;
54 int tm_min;
55 int tm_sec;
56 } fake_tm;
57
58 /* The mktime_utc function is due to Russ Allbery (rra@stanford.edu),
59 * who placed it under public domain:
60 */
61
62 /* The number of days in each month.
63 */
64 static const int MONTHDAYS[] = {
65 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
66 };
67
68 /* Whether a given year is a leap year. */
69 #define ISLEAP(year) \
70 (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0))
71
72 /*
73 ** Given a struct tm representing a calendar time in UTC, convert it to
74 ** seconds since epoch. Returns (time_t) -1 if the time is not
75 ** convertible. Note that this function does not canonicalize the provided
76 ** struct tm, nor does it allow out of range values or years before 1970.
77 */
mktime_utc(const struct fake_tm * tm)78 static time_t mktime_utc(const struct fake_tm *tm)
79 {
80 time_t result = 0;
81 int i;
82
83 /* We do allow some ill-formed dates, but we don't do anything special
84 * with them and our callers really shouldn't pass them to us. Do
85 * explicitly disallow the ones that would cause invalid array accesses
86 * or other algorithm problems.
87 */
88 if (tm->tm_mon < 0 || tm->tm_mon > 11 || tm->tm_year < 1970)
89 return (time_t) - 1;
90
91 /* Check for "obvious" mistakes in dates */
92 if (tm->tm_sec > 60 || tm->tm_min > 59 || tm->tm_mday > 31 || tm->tm_mday < 1 || tm->tm_hour > 23)
93 return (time_t) - 1;
94
95 /* Convert to a time_t.
96 */
97 for (i = 1970; i < tm->tm_year; i++)
98 result += 365 + ISLEAP(i);
99 for (i = 0; i < tm->tm_mon; i++)
100 result += MONTHDAYS[i];
101 if (tm->tm_mon > 1 && ISLEAP(tm->tm_year))
102 result++;
103 result = 24 * (result + tm->tm_mday - 1) + tm->tm_hour;
104 result = 60 * result + tm->tm_min;
105 result = 60 * result + tm->tm_sec;
106 return result;
107 }
108
109
110 /* this one will parse dates of the form:
111 * month|day|hour|minute|sec* (2 chars each)
112 * and year is given. Returns a time_t date.
113 */
time2gtime(const char * ttime,int year)114 static time_t time2gtime(const char *ttime, int year)
115 {
116 char xx[4];
117 struct fake_tm etime;
118
119 if (strlen(ttime) < 8) {
120 gnutls_assert();
121 return (time_t) - 1;
122 }
123
124 etime.tm_year = year;
125
126 /* In order to work with 32 bit
127 * time_t.
128 */
129 if (sizeof(time_t) <= 4 && etime.tm_year >= 2038)
130 return (time_t) 2145914603; /* 2037-12-31 23:23:23 */
131
132 if (etime.tm_year < 1970)
133 return (time_t) 0;
134
135 xx[2] = 0;
136
137 /* get the month
138 */
139 memcpy(xx, ttime, 2); /* month */
140 etime.tm_mon = atoi(xx) - 1;
141 ttime += 2;
142
143 /* get the day
144 */
145 memcpy(xx, ttime, 2); /* day */
146 etime.tm_mday = atoi(xx);
147 ttime += 2;
148
149 /* get the hour
150 */
151 memcpy(xx, ttime, 2); /* hour */
152 etime.tm_hour = atoi(xx);
153 ttime += 2;
154
155 /* get the minutes
156 */
157 memcpy(xx, ttime, 2); /* minutes */
158 etime.tm_min = atoi(xx);
159 ttime += 2;
160
161 if (strlen(ttime) >= 2) {
162 memcpy(xx, ttime, 2);
163 etime.tm_sec = atoi(xx);
164 } else
165 etime.tm_sec = 0;
166
167 return mktime_utc(&etime);
168 }
169
170
171 /* returns a time_t value that contains the given time.
172 * The given time is expressed as:
173 * YEAR(2)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2)*
174 *
175 * (seconds are optional)
176 */
_gnutls_utcTime2gtime(const char * ttime)177 time_t _gnutls_utcTime2gtime(const char *ttime)
178 {
179 char xx[3];
180 int year, i;
181 int len = strlen(ttime);
182
183 if (len < 10) {
184 gnutls_assert();
185 return (time_t) - 1;
186 }
187
188 #ifdef STRICT_DER_TIME
189 /* Make sure everything else is digits. */
190 for (i = 0; i < len - 1; i++) {
191 if (c_isdigit(ttime[i]))
192 continue;
193 return gnutls_assert_val((time_t)-1);
194 }
195 #endif
196 xx[2] = 0;
197
198 /* get the year
199 */
200 memcpy(xx, ttime, 2); /* year */
201 year = atoi(xx);
202 ttime += 2;
203
204 if (year > 49)
205 year += 1900;
206 else
207 year += 2000;
208
209 return time2gtime(ttime, year);
210 }
211
212 /* returns a time_t value that contains the given time.
213 * The given time is expressed as:
214 * YEAR(4)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2)*
215 */
_gnutls_x509_generalTime2gtime(const char * ttime)216 time_t _gnutls_x509_generalTime2gtime(const char *ttime)
217 {
218 char xx[5];
219 int year;
220
221 if (strlen(ttime) < 12) {
222 gnutls_assert();
223 return (time_t) - 1;
224 }
225
226 if (strchr(ttime, 'Z') == 0) {
227 gnutls_assert();
228 /* required to be in GMT */
229 return (time_t) - 1;
230 }
231
232 if (strchr(ttime, '.') != 0) {
233 gnutls_assert();
234 /* no fractional seconds allowed */
235 return (time_t) - 1;
236 }
237 xx[4] = 0;
238
239 /* get the year
240 */
241 memcpy(xx, ttime, 4); /* year */
242 year = atoi(xx);
243 ttime += 4;
244
245 return time2gtime(ttime, year);
246 }
247
248 /* tag will contain ASN1_TAG_UTCTime or ASN1_TAG_GENERALIZEDTime */
249 static int
gtime_to_suitable_time(time_t gtime,char * str_time,size_t str_time_size,unsigned * tag)250 gtime_to_suitable_time(time_t gtime, char *str_time, size_t str_time_size, unsigned *tag)
251 {
252 size_t ret;
253 struct tm _tm;
254
255 if (gtime == (time_t)-1
256 #if SIZEOF_LONG == 8
257 || gtime >= 253402210800
258 #endif
259 ) {
260 if (tag)
261 *tag = ASN1_TAG_GENERALIZEDTime;
262 snprintf(str_time, str_time_size, "99991231235959Z");
263 return 0;
264 }
265
266 if (!gmtime_r(>ime, &_tm)) {
267 gnutls_assert();
268 return GNUTLS_E_INTERNAL_ERROR;
269 }
270
271 if (_tm.tm_year >= 150) {
272 if (tag)
273 *tag = ASN1_TAG_GENERALIZEDTime;
274 ret = strftime(str_time, str_time_size, "%Y%m%d%H%M%SZ", &_tm);
275 } else {
276 if (tag)
277 *tag = ASN1_TAG_UTCTime;
278 ret = strftime(str_time, str_time_size, "%y%m%d%H%M%SZ", &_tm);
279 }
280
281 if (!ret) {
282 gnutls_assert();
283 return GNUTLS_E_SHORT_MEMORY_BUFFER;
284 }
285
286 return 0;
287 }
288
289 static int
gtime_to_generalTime(time_t gtime,char * str_time,size_t str_time_size)290 gtime_to_generalTime(time_t gtime, char *str_time, size_t str_time_size)
291 {
292 size_t ret;
293 struct tm _tm;
294
295 if (gtime == (time_t)-1
296 #if SIZEOF_LONG == 8
297 || gtime >= 253402210800
298 #endif
299 ) {
300 snprintf(str_time, str_time_size, "99991231235959Z");
301 return 0;
302 }
303
304 if (!gmtime_r(>ime, &_tm)) {
305 gnutls_assert();
306 return GNUTLS_E_INTERNAL_ERROR;
307 }
308
309 ret = strftime(str_time, str_time_size, "%Y%m%d%H%M%SZ", &_tm);
310 if (!ret) {
311 gnutls_assert();
312 return GNUTLS_E_SHORT_MEMORY_BUFFER;
313 }
314
315 return 0;
316 }
317
318
319 /* Extracts the time in time_t from the ASN1_TYPE given. When should
320 * be something like "tbsCertList.thisUpdate".
321 */
322 #define MAX_TIME 64
_gnutls_x509_get_time(ASN1_TYPE c2,const char * where,int force_general)323 time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *where, int force_general)
324 {
325 char ttime[MAX_TIME];
326 char name[128];
327 time_t c_time = (time_t) - 1;
328 int len, result;
329
330 len = sizeof(ttime) - 1;
331 result = asn1_read_value(c2, where, ttime, &len);
332 if (result != ASN1_SUCCESS) {
333 gnutls_assert();
334 return (time_t) (-1);
335 }
336
337 if (force_general != 0) {
338 c_time = _gnutls_x509_generalTime2gtime(ttime);
339 } else {
340 _gnutls_str_cpy(name, sizeof(name), where);
341
342 /* choice */
343 if (strcmp(ttime, "generalTime") == 0) {
344 if (name[0] == 0)
345 _gnutls_str_cpy(name, sizeof(name),
346 "generalTime");
347 else
348 _gnutls_str_cat(name, sizeof(name),
349 ".generalTime");
350 len = sizeof(ttime) - 1;
351 result = asn1_read_value(c2, name, ttime, &len);
352 if (result == ASN1_SUCCESS)
353 c_time =
354 _gnutls_x509_generalTime2gtime(ttime);
355 } else { /* UTCTIME */
356 if (name[0] == 0)
357 _gnutls_str_cpy(name, sizeof(name), "utcTime");
358 else
359 _gnutls_str_cat(name, sizeof(name), ".utcTime");
360 len = sizeof(ttime) - 1;
361 result = asn1_read_value(c2, name, ttime, &len);
362 if (result == ASN1_SUCCESS)
363 c_time = _gnutls_utcTime2gtime(ttime);
364 }
365
366 /* We cannot handle dates after 2031 in 32 bit machines.
367 * a time_t of 64bits has to be used.
368 */
369 if (result != ASN1_SUCCESS) {
370 gnutls_assert();
371 return (time_t) (-1);
372 }
373 }
374
375 return c_time;
376 }
377
378 /* Sets the time in time_t in the ASN1_TYPE given. Where should
379 * be something like "tbsCertList.thisUpdate".
380 */
381 int
_gnutls_x509_set_time(ASN1_TYPE c2,const char * where,time_t tim,int force_general)382 _gnutls_x509_set_time(ASN1_TYPE c2, const char *where, time_t tim,
383 int force_general)
384 {
385 char str_time[MAX_TIME];
386 char name[128];
387 int result, len;
388 unsigned tag;
389
390 if (force_general != 0) {
391 result =
392 gtime_to_generalTime(tim, str_time, sizeof(str_time));
393 if (result < 0)
394 return gnutls_assert_val(result);
395 len = strlen(str_time);
396 result = asn1_write_value(c2, where, str_time, len);
397 if (result != ASN1_SUCCESS)
398 return gnutls_assert_val(_gnutls_asn2err(result));
399
400 return 0;
401 }
402
403 result = gtime_to_suitable_time(tim, str_time, sizeof(str_time), &tag);
404 if (result < 0) {
405 gnutls_assert();
406 return result;
407 }
408
409 _gnutls_str_cpy(name, sizeof(name), where);
410 if (tag == ASN1_TAG_UTCTime) {
411 if ((result = asn1_write_value(c2, where, "utcTime", 1)) < 0) {
412 gnutls_assert();
413 return _gnutls_asn2err(result);
414 }
415 _gnutls_str_cat(name, sizeof(name), ".utcTime");
416 } else {
417 if ((result = asn1_write_value(c2, where, "generalTime", 1)) < 0) {
418 gnutls_assert();
419 return _gnutls_asn2err(result);
420 }
421 _gnutls_str_cat(name, sizeof(name), ".generalTime");
422 }
423
424 len = strlen(str_time);
425 result = asn1_write_value(c2, name, str_time, len);
426 if (result != ASN1_SUCCESS) {
427 gnutls_assert();
428 return _gnutls_asn2err(result);
429 }
430
431 return 0;
432 }
433
434 /* This will set a DER encoded Time element. To be used in fields
435 * which are of the ANY.
436 */
437 int
_gnutls_x509_set_raw_time(ASN1_TYPE c2,const char * where,time_t tim)438 _gnutls_x509_set_raw_time(ASN1_TYPE c2, const char *where, time_t tim)
439 {
440 char str_time[MAX_TIME];
441 uint8_t buf[128];
442 int result, len, der_len;
443 unsigned tag;
444
445 result =
446 gtime_to_suitable_time(tim, str_time, sizeof(str_time), &tag);
447 if (result < 0)
448 return gnutls_assert_val(result);
449 len = strlen(str_time);
450
451 buf[0] = tag;
452 asn1_length_der(len, buf+1, &der_len);
453
454 if ((unsigned)len > sizeof(buf)-der_len-1) {
455 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
456 }
457
458 memcpy(buf+1+der_len, str_time, len);
459
460 result = asn1_write_value(c2, where, buf, len+1+der_len);
461 if (result != ASN1_SUCCESS)
462 return gnutls_assert_val(_gnutls_asn2err(result));
463 return 0;
464 }
465
466