Line data Source code
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 : */
78 80301 : static time_t mktime_utc(const struct fake_tm *tm)
79 : {
80 80301 : time_t result = 0;
81 80301 : 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 80301 : 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 80189 : 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 127383000 : for (i = 1970; i < tm->tm_year; i++)
98 223722000 : result += 365 + ISLEAP(i);
99 582412 : for (i = 0; i < tm->tm_mon; i++)
100 502320 : result += MONTHDAYS[i];
101 80092 : if (tm->tm_mon > 1 && ISLEAP(tm->tm_year))
102 13860 : result++;
103 80092 : result = 24 * (result + tm->tm_mday - 1) + tm->tm_hour;
104 80092 : result = 60 * result + tm->tm_min;
105 80092 : result = 60 * result + tm->tm_sec;
106 80092 : 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 : */
114 80600 : static time_t time2gtime(const char *ttime, int year)
115 : {
116 80600 : char xx[4];
117 80600 : struct fake_tm etime;
118 :
119 80600 : if (strlen(ttime) < 8) {
120 0 : gnutls_assert();
121 0 : return (time_t) - 1;
122 : }
123 :
124 80600 : etime.tm_year = year;
125 :
126 : /* In order to work with 32 bit
127 : * time_t.
128 : */
129 80600 : if (sizeof(time_t) <= 4 && etime.tm_year >= 2038)
130 : return (time_t) 2145914603; /* 2037-12-31 23:23:23 */
131 :
132 80600 : if (etime.tm_year < 1970)
133 : return (time_t) 0;
134 :
135 80301 : xx[2] = 0;
136 :
137 : /* get the month
138 : */
139 80301 : memcpy(xx, ttime, 2); /* month */
140 80301 : etime.tm_mon = atoi(xx) - 1;
141 80301 : ttime += 2;
142 :
143 : /* get the day
144 : */
145 80301 : memcpy(xx, ttime, 2); /* day */
146 80301 : etime.tm_mday = atoi(xx);
147 80301 : ttime += 2;
148 :
149 : /* get the hour
150 : */
151 80301 : memcpy(xx, ttime, 2); /* hour */
152 80301 : etime.tm_hour = atoi(xx);
153 80301 : ttime += 2;
154 :
155 : /* get the minutes
156 : */
157 80301 : memcpy(xx, ttime, 2); /* minutes */
158 80301 : etime.tm_min = atoi(xx);
159 80301 : ttime += 2;
160 :
161 80301 : if (strlen(ttime) >= 2) {
162 80271 : memcpy(xx, ttime, 2);
163 80271 : etime.tm_sec = atoi(xx);
164 : } else
165 30 : etime.tm_sec = 0;
166 :
167 80301 : 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 : */
177 55655 : time_t _gnutls_utcTime2gtime(const char *ttime)
178 : {
179 55655 : char xx[3];
180 55655 : int year, i;
181 55655 : int len = strlen(ttime);
182 :
183 55655 : if (len < 10) {
184 0 : gnutls_assert();
185 0 : return (time_t) - 1;
186 : }
187 :
188 : #ifdef STRICT_DER_TIME
189 : /* Make sure everything else is digits. */
190 723490 : for (i = 0; i < len - 1; i++) {
191 667835 : if (c_isdigit(ttime[i]))
192 667835 : continue;
193 0 : return gnutls_assert_val((time_t)-1);
194 : }
195 : #endif
196 55655 : xx[2] = 0;
197 :
198 : /* get the year
199 : */
200 55655 : memcpy(xx, ttime, 2); /* year */
201 55655 : year = atoi(xx);
202 55655 : ttime += 2;
203 :
204 55655 : if (year > 49)
205 2503 : year += 1900;
206 : else
207 53152 : year += 2000;
208 :
209 55655 : 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 : */
216 24959 : time_t _gnutls_x509_generalTime2gtime(const char *ttime)
217 : {
218 24959 : char xx[5];
219 24959 : int year;
220 :
221 24959 : if (strlen(ttime) < 12) {
222 0 : gnutls_assert();
223 0 : return (time_t) - 1;
224 : }
225 :
226 24959 : if (strchr(ttime, 'Z') == 0) {
227 0 : gnutls_assert();
228 : /* required to be in GMT */
229 0 : return (time_t) - 1;
230 : }
231 :
232 24959 : if (strchr(ttime, '.') != 0) {
233 14 : gnutls_assert();
234 : /* no fractional seconds allowed */
235 14 : return (time_t) - 1;
236 : }
237 24945 : xx[4] = 0;
238 :
239 : /* get the year
240 : */
241 24945 : memcpy(xx, ttime, 4); /* year */
242 24945 : year = atoi(xx);
243 24945 : ttime += 4;
244 :
245 24945 : return time2gtime(ttime, year);
246 : }
247 :
248 : #pragma GCC diagnostic push
249 : #pragma GCC diagnostic ignored "-Wformat-y2k"
250 : /* tag will contain ASN1_TAG_UTCTime or ASN1_TAG_GENERALIZEDTime */
251 : static int
252 829 : gtime_to_suitable_time(time_t gtime, char *str_time, size_t str_time_size, unsigned *tag)
253 : {
254 829 : size_t ret;
255 829 : struct tm _tm;
256 :
257 829 : if (gtime == (time_t)-1
258 : #if SIZEOF_LONG == 8
259 829 : || gtime >= 253402210800
260 : #endif
261 : ) {
262 6 : if (tag)
263 6 : *tag = ASN1_TAG_GENERALIZEDTime;
264 6 : snprintf(str_time, str_time_size, "99991231235959Z");
265 6 : return 0;
266 : }
267 :
268 823 : if (!gmtime_r(>ime, &_tm)) {
269 0 : gnutls_assert();
270 0 : return GNUTLS_E_INTERNAL_ERROR;
271 : }
272 :
273 823 : if (_tm.tm_year >= 150) {
274 157 : if (tag)
275 157 : *tag = ASN1_TAG_GENERALIZEDTime;
276 157 : ret = strftime(str_time, str_time_size, "%Y%m%d%H%M%SZ", &_tm);
277 : } else {
278 666 : if (tag)
279 666 : *tag = ASN1_TAG_UTCTime;
280 666 : ret = strftime(str_time, str_time_size, "%y%m%d%H%M%SZ", &_tm);
281 : }
282 :
283 823 : if (!ret) {
284 0 : gnutls_assert();
285 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
286 : }
287 :
288 : return 0;
289 : }
290 : #pragma GCC diagnostic pop
291 :
292 : static int
293 2 : gtime_to_generalTime(time_t gtime, char *str_time, size_t str_time_size)
294 : {
295 2 : size_t ret;
296 2 : struct tm _tm;
297 :
298 2 : if (gtime == (time_t)-1
299 : #if SIZEOF_LONG == 8
300 2 : || gtime >= 253402210800
301 : #endif
302 : ) {
303 0 : snprintf(str_time, str_time_size, "99991231235959Z");
304 0 : return 0;
305 : }
306 :
307 2 : if (!gmtime_r(>ime, &_tm)) {
308 0 : gnutls_assert();
309 0 : return GNUTLS_E_INTERNAL_ERROR;
310 : }
311 :
312 2 : ret = strftime(str_time, str_time_size, "%Y%m%d%H%M%SZ", &_tm);
313 2 : if (!ret) {
314 0 : gnutls_assert();
315 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
316 : }
317 :
318 : return 0;
319 : }
320 :
321 :
322 : /* Extracts the time in time_t from the ASN1_TYPE given. When should
323 : * be something like "tbsCertList.thisUpdate".
324 : */
325 : #define MAX_TIME 64
326 79800 : time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *where, int force_general)
327 : {
328 79800 : char ttime[MAX_TIME];
329 79800 : char name[128];
330 79800 : time_t c_time = (time_t) - 1;
331 79800 : int len, result;
332 :
333 79800 : len = sizeof(ttime) - 1;
334 79800 : result = asn1_read_value(c2, where, ttime, &len);
335 79800 : if (result != ASN1_SUCCESS) {
336 4 : gnutls_assert();
337 4 : return (time_t) (-1);
338 : }
339 :
340 79796 : if (force_general != 0) {
341 16 : c_time = _gnutls_x509_generalTime2gtime(ttime);
342 : } else {
343 79780 : _gnutls_str_cpy(name, sizeof(name), where);
344 :
345 : /* choice */
346 79780 : if (strcmp(ttime, "generalTime") == 0) {
347 24124 : if (name[0] == 0)
348 0 : _gnutls_str_cpy(name, sizeof(name),
349 : "generalTime");
350 : else
351 24124 : _gnutls_str_cat(name, sizeof(name),
352 : ".generalTime");
353 24124 : len = sizeof(ttime) - 1;
354 24124 : result = asn1_read_value(c2, name, ttime, &len);
355 24124 : if (result == ASN1_SUCCESS)
356 24124 : c_time =
357 24124 : _gnutls_x509_generalTime2gtime(ttime);
358 : } else { /* UTCTIME */
359 55656 : if (name[0] == 0)
360 46 : _gnutls_str_cpy(name, sizeof(name), "utcTime");
361 : else
362 55610 : _gnutls_str_cat(name, sizeof(name), ".utcTime");
363 55656 : len = sizeof(ttime) - 1;
364 55656 : result = asn1_read_value(c2, name, ttime, &len);
365 55656 : if (result == ASN1_SUCCESS)
366 55653 : c_time = _gnutls_utcTime2gtime(ttime);
367 : }
368 :
369 : /* We cannot handle dates after 2031 in 32 bit machines.
370 : * a time_t of 64bits has to be used.
371 : */
372 79780 : if (result != ASN1_SUCCESS) {
373 3 : gnutls_assert();
374 3 : return (time_t) (-1);
375 : }
376 : }
377 :
378 : return c_time;
379 : }
380 :
381 : /* Sets the time in time_t in the ASN1_TYPE given. Where should
382 : * be something like "tbsCertList.thisUpdate".
383 : */
384 : int
385 829 : _gnutls_x509_set_time(ASN1_TYPE c2, const char *where, time_t tim,
386 : int force_general)
387 : {
388 829 : char str_time[MAX_TIME];
389 829 : char name[128];
390 829 : int result, len;
391 829 : unsigned tag;
392 :
393 829 : if (force_general != 0) {
394 2 : result =
395 2 : gtime_to_generalTime(tim, str_time, sizeof(str_time));
396 2 : if (result < 0)
397 0 : return gnutls_assert_val(result);
398 2 : len = strlen(str_time);
399 2 : result = asn1_write_value(c2, where, str_time, len);
400 2 : if (result != ASN1_SUCCESS)
401 0 : return gnutls_assert_val(_gnutls_asn2err(result));
402 :
403 : return 0;
404 : }
405 :
406 827 : result = gtime_to_suitable_time(tim, str_time, sizeof(str_time), &tag);
407 827 : if (result < 0) {
408 0 : gnutls_assert();
409 0 : return result;
410 : }
411 :
412 827 : _gnutls_str_cpy(name, sizeof(name), where);
413 827 : if (tag == ASN1_TAG_UTCTime) {
414 664 : if ((result = asn1_write_value(c2, where, "utcTime", 1)) < 0) {
415 0 : gnutls_assert();
416 0 : return _gnutls_asn2err(result);
417 : }
418 664 : _gnutls_str_cat(name, sizeof(name), ".utcTime");
419 : } else {
420 163 : if ((result = asn1_write_value(c2, where, "generalTime", 1)) < 0) {
421 0 : gnutls_assert();
422 0 : return _gnutls_asn2err(result);
423 : }
424 163 : _gnutls_str_cat(name, sizeof(name), ".generalTime");
425 : }
426 :
427 827 : len = strlen(str_time);
428 827 : result = asn1_write_value(c2, name, str_time, len);
429 827 : if (result != ASN1_SUCCESS) {
430 0 : gnutls_assert();
431 0 : return _gnutls_asn2err(result);
432 : }
433 :
434 : return 0;
435 : }
436 :
437 : /* This will set a DER encoded Time element. To be used in fields
438 : * which are of the ANY.
439 : */
440 : int
441 2 : _gnutls_x509_set_raw_time(ASN1_TYPE c2, const char *where, time_t tim)
442 : {
443 2 : char str_time[MAX_TIME];
444 2 : uint8_t buf[128];
445 2 : int result, len, der_len;
446 2 : unsigned tag;
447 :
448 2 : result =
449 2 : gtime_to_suitable_time(tim, str_time, sizeof(str_time), &tag);
450 2 : if (result < 0)
451 0 : return gnutls_assert_val(result);
452 2 : len = strlen(str_time);
453 :
454 2 : buf[0] = tag;
455 2 : asn1_length_der(len, buf+1, &der_len);
456 :
457 2 : if ((unsigned)len > sizeof(buf)-der_len-1) {
458 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
459 : }
460 :
461 2 : memcpy(buf+1+der_len, str_time, len);
462 :
463 2 : result = asn1_write_value(c2, where, buf, len+1+der_len);
464 2 : if (result != ASN1_SUCCESS)
465 0 : return gnutls_assert_val(_gnutls_asn2err(result));
466 : return 0;
467 : }
468 :
|