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(&gtime, &_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(&gtime, &_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