mirror of https://github.com/openssl/openssl.git
				
				
				
			Experimental new date handling routines. These fix issues with X509_time_adj()
and should avoid any OS date limitations such as the year 2038 bug.
This commit is contained in:
		
							parent
							
								
									1e369b375e
								
							
						
					
					
						commit
						87d3a0cd90
					
				
							
								
								
									
										8
									
								
								CHANGES
								
								
								
								
							
							
						
						
									
										8
									
								
								CHANGES
								
								
								
								
							|  | @ -4,6 +4,14 @@ | |||
| 
 | ||||
|  Changes between 0.9.8j and 0.9.9  [xx XXX xxxx] | ||||
| 
 | ||||
|   *) New function OPENSSL_gmtime_adj() to add a specific number of days and | ||||
|      seconds to a tm structure directly, instead of going through OS | ||||
|      specific date routines. This avoids any issues with OS routines such | ||||
|      as the year 2038 bug. New *_adj() functions for ASN1 time structures | ||||
|      and X509_time_adj_ex() to cover the extended range. The existing | ||||
|      X509_time_adj() is still usable and will no longer have any date issues. | ||||
|      [Steve Henson] | ||||
| 
 | ||||
|   *) Delta CRL support. New use deltas option which will attempt to locate | ||||
|      and search any appropriate delta CRLs available. | ||||
| 
 | ||||
|  |  | |||
|  | @ -1399,7 +1399,7 @@ bad: | |||
| 		if (!tmptm) goto err; | ||||
| 		X509_gmtime_adj(tmptm,0); | ||||
| 		X509_CRL_set_lastUpdate(crl, tmptm);	 | ||||
| 		X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60 + crlsec); | ||||
| 		X509_time_adj_ex(tmptm, crldays, crlhours*60*60 + crlsec, NULL); | ||||
| 		X509_CRL_set_nextUpdate(crl, tmptm);	 | ||||
| 
 | ||||
| 		ASN1_TIME_free(tmptm); | ||||
|  | @ -2006,7 +2006,7 @@ again2: | |||
| 	else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate); | ||||
| 
 | ||||
| 	if (enddate == NULL) | ||||
| 		X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days); | ||||
| 		X509_time_adj_ex(X509_get_notAfter(ret),days, 0, NULL); | ||||
| 	else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate); | ||||
| 
 | ||||
| 	if (!X509_set_subject_name(ret,subject)) goto err; | ||||
|  |  | |||
|  | @ -838,7 +838,7 @@ loop: | |||
| 
 | ||||
| 			if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) goto end; | ||||
| 			if (!X509_gmtime_adj(X509_get_notBefore(x509ss),0)) goto end; | ||||
| 			if (!X509_gmtime_adj(X509_get_notAfter(x509ss), (long)60*60*24*days)) goto end; | ||||
| 			if (!X509_time_adj_ex(X509_get_notAfter(x509ss), days, 0, NULL)) goto end; | ||||
| 			if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req))) goto end; | ||||
| 			tmppkey = X509_REQ_get_pubkey(req); | ||||
| 			if (!tmppkey || !X509_set_pubkey(x509ss,tmppkey)) goto end; | ||||
|  |  | |||
|  | @ -210,6 +210,12 @@ int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) | |||
| 
 | ||||
| ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, | ||||
| 	     time_t t) | ||||
| 	{ | ||||
| 		return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0); | ||||
| 	} | ||||
| 
 | ||||
| ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, | ||||
| 	     time_t t, int offset_day, long offset_sec) | ||||
| 	{ | ||||
| 	char *p; | ||||
| 	struct tm *ts; | ||||
|  | @ -225,6 +231,12 @@ ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, | |||
| 	if (ts == NULL) | ||||
| 		return(NULL); | ||||
| 
 | ||||
| 	if (offset_day || offset_sec) | ||||
| 		{  | ||||
| 		if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) | ||||
| 			return NULL; | ||||
| 		} | ||||
| 
 | ||||
| 	p=(char *)s->data; | ||||
| 	if ((p == NULL) || ((size_t)s->length < len)) | ||||
| 		{ | ||||
|  |  | |||
|  | @ -100,6 +100,12 @@ int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp) | |||
| 
 | ||||
| ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) | ||||
| 	{ | ||||
| 	return ASN1_TIME_adj(s, t, 0, 0); | ||||
| 	} | ||||
| 
 | ||||
| ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, | ||||
| 				int offset_day, long offset_sec) | ||||
| 	{ | ||||
| 	struct tm *ts; | ||||
| 	struct tm data; | ||||
| 
 | ||||
|  | @ -109,9 +115,14 @@ ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) | |||
| 		ASN1err(ASN1_F_ASN1_TIME_SET, ASN1_R_ERROR_GETTING_TIME); | ||||
| 		return NULL; | ||||
| 		} | ||||
| 	if (offset_day || offset_sec) | ||||
| 		{  | ||||
| 		if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) | ||||
| 			return NULL; | ||||
| 		} | ||||
| 	if((ts->tm_year >= 50) && (ts->tm_year < 150)) | ||||
| 					return ASN1_UTCTIME_set(s, t); | ||||
| 	return ASN1_GENERALIZEDTIME_set(s,t); | ||||
| 			return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); | ||||
| 	return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); | ||||
| 	} | ||||
| 
 | ||||
| int ASN1_TIME_check(ASN1_TIME *t) | ||||
|  |  | |||
|  | @ -186,6 +186,12 @@ int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) | |||
| 
 | ||||
| ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) | ||||
| 	{ | ||||
| 	return ASN1_UTCTIME_adj(s, t, 0, 0); | ||||
| 	} | ||||
| 
 | ||||
| ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, | ||||
| 				int offset_day, long offset_sec) | ||||
| 	{ | ||||
| 	char *p; | ||||
| 	struct tm *ts; | ||||
| 	struct tm data; | ||||
|  | @ -200,6 +206,15 @@ ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) | |||
| 	if (ts == NULL) | ||||
| 		return(NULL); | ||||
| 
 | ||||
| 	if (offset_day || offset_sec) | ||||
| 		{  | ||||
| 		if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) | ||||
| 			return NULL; | ||||
| 		} | ||||
| 
 | ||||
| 	if((ts->tm_year < 50) || (ts->tm_year >= 150)) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	p=(char *)s->data; | ||||
| 	if ((p == NULL) || ((size_t)s->length < len)) | ||||
| 		{ | ||||
|  |  | |||
|  | @ -837,6 +837,8 @@ DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED) | |||
| 
 | ||||
| int ASN1_UTCTIME_check(ASN1_UTCTIME *a); | ||||
| ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s,time_t t); | ||||
| ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, | ||||
| 				int offset_day, long offset_sec); | ||||
| int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str); | ||||
| int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t); | ||||
| #if 0 | ||||
|  | @ -845,6 +847,8 @@ time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s); | |||
| 
 | ||||
| int ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *a); | ||||
| ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,time_t t); | ||||
| ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, | ||||
| 	     time_t t, int offset_day, long offset_sec); | ||||
| int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str); | ||||
| 
 | ||||
| DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING) | ||||
|  | @ -876,6 +880,8 @@ DECLARE_ASN1_FUNCTIONS(ASN1_TIME) | |||
| DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF) | ||||
| 
 | ||||
| ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s,time_t t); | ||||
| ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s,time_t t, | ||||
| 				int offset_day, long offset_sec); | ||||
| int ASN1_TIME_check(ASN1_TIME *t); | ||||
| ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out); | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										151
									
								
								crypto/o_time.c
								
								
								
								
							
							
						
						
									
										151
									
								
								crypto/o_time.c
								
								
								
								
							|  | @ -2,6 +2,9 @@ | |||
| /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
 | ||||
|  * project 2001. | ||||
|  */ | ||||
| /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
 | ||||
|  * project 2008. | ||||
|  */ | ||||
| /* ====================================================================
 | ||||
|  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved. | ||||
|  * | ||||
|  | @ -214,4 +217,150 @@ struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result) | |||
| 		} | ||||
| #endif | ||||
| 	return ts; | ||||
| 	}	 | ||||
| 	} | ||||
| 
 | ||||
| /* Take a tm structure and add an offset to it. This avoids any OS issues
 | ||||
|  * with restricted date types and overflows which cause the year 2038 | ||||
|  * problem. | ||||
|  */ | ||||
| 
 | ||||
| #define SECS_PER_DAY (24 * 60 * 60) | ||||
| 
 | ||||
| static long date_to_julian(int y, int m, int d); | ||||
| static void julian_to_date(long jd, int *y, int *m, int *d); | ||||
| 
 | ||||
| int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) | ||||
| 	{ | ||||
| 	int offset_hms, offset_day; | ||||
| 	long time_jd; | ||||
| 	int time_year, time_month, time_day; | ||||
| 	/* split offset into days and day seconds */ | ||||
| 	offset_day = offset_sec / SECS_PER_DAY; | ||||
| 	/* Avoid sign issues with % operator */ | ||||
| 	offset_hms  = offset_sec - (offset_day * SECS_PER_DAY); | ||||
| 	offset_day += off_day; | ||||
| 	/* Add current time seconds to offset */ | ||||
| 	offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; | ||||
| 	/* Adjust day seconds if overflow */ | ||||
| 	if (offset_hms >= SECS_PER_DAY) | ||||
| 		{ | ||||
| 		offset_day++; | ||||
| 		offset_hms -= SECS_PER_DAY; | ||||
| 		} | ||||
| 	else if (offset_hms < 0) | ||||
| 		{ | ||||
| 		offset_day--; | ||||
| 		offset_hms += SECS_PER_DAY; | ||||
| 		} | ||||
| 
 | ||||
| 	/* Convert date of time structure into a Julian day number.
 | ||||
| 	 */ | ||||
| 
 | ||||
| 	time_year = tm->tm_year + 1900; | ||||
| 	time_month = tm->tm_mon + 1; | ||||
| 	time_day = tm->tm_mday; | ||||
| 
 | ||||
| 	time_jd = date_to_julian(time_year, time_month, time_day); | ||||
| 
 | ||||
| 	/* Work out Julian day of new date */ | ||||
| 	time_jd += offset_day; | ||||
| 
 | ||||
| 	if (time_jd < 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* Convert Julian day back to date */ | ||||
| 
 | ||||
| 	julian_to_date(time_jd, &time_year, &time_month, &time_day); | ||||
| 
 | ||||
| 	if (time_year < 1900 || time_year > 9999) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* Update tm structure */ | ||||
| 
 | ||||
| 	tm->tm_year = time_year - 1900; | ||||
| 	tm->tm_mon = time_month - 1; | ||||
| 	tm->tm_mday = time_day; | ||||
| 
 | ||||
| 	tm->tm_hour = offset_hms / 3600; | ||||
| 	tm->tm_min = (offset_hms / 60) % 60; | ||||
| 	tm->tm_sec = offset_hms % 60; | ||||
| 
 | ||||
| 	return 1; | ||||
| 		 | ||||
| } | ||||
| 
 | ||||
| /* Convert date to and from julian day
 | ||||
|  * Uses Fliegel & Van Flandern algorithm | ||||
|  */ | ||||
| static long date_to_julian(int y, int m, int d) | ||||
| { | ||||
| 	return (1461 * (y + 4800 + (m - 14) / 12)) / 4 + | ||||
| 		(367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 - | ||||
| 		(3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + | ||||
| 		d - 32075; | ||||
| } | ||||
| 
 | ||||
| static void julian_to_date(long jd, int *y, int *m, int *d) | ||||
| 	{ | ||||
| 	long  L = jd + 68569; | ||||
| 	long  n = (4 * L) / 146097; | ||||
| 	long  i, j; | ||||
| 
 | ||||
| 	L = L - (146097 * n + 3) / 4; | ||||
| 	i = (4000 * (L + 1)) / 1461001; | ||||
| 	L = L - (1461 * i) / 4 + 31; | ||||
| 	j = (80 * L) / 2447; | ||||
| 	*d = L - (2447 * j) / 80; | ||||
| 	L = j / 11; | ||||
| 	*m = j + 2 - (12 * L); | ||||
| 	*y = 100 * (n - 49) + i + L; | ||||
| 	} | ||||
| 
 | ||||
| #ifdef OPENSSL_TIME_TEST | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| /* Time checking test code. Check times are identical for a wide range of
 | ||||
|  * offsets. This should be run on a machine with 64 bit time_t or it will | ||||
|  * trigger the very errors the routines fix. | ||||
|  */ | ||||
| 
 | ||||
| int main(int argc, char **argv) | ||||
| 	{ | ||||
| 	long offset; | ||||
| 	for (offset = 0; offset < 1000000; offset++) | ||||
| 		{ | ||||
| 		check_time(offset); | ||||
| 		check_time(-offset); | ||||
| 		check_time(offset * 1000); | ||||
| 		check_time(-offset * 1000); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| int check_time(long offset) | ||||
| 	{ | ||||
| 	struct tm tm1, tm2; | ||||
| 	time_t t1, t2; | ||||
| 	time(&t1); | ||||
| 	t2 = t1 + offset; | ||||
| 	OPENSSL_gmtime(&t2, &tm2); | ||||
| 	OPENSSL_gmtime(&t1, &tm1); | ||||
| 	OPENSSL_gmtime_adj(&tm1, 0, offset); | ||||
| 	if ((tm1.tm_year == tm2.tm_year) && | ||||
| 	    (tm1.tm_mon == tm2.tm_mon) && | ||||
| 	    (tm1.tm_mday == tm2.tm_mday) && | ||||
| 	    (tm1.tm_hour == tm2.tm_hour) && | ||||
| 	    (tm1.tm_min == tm2.tm_min) && | ||||
| 	    (tm1.tm_sec == tm2.tm_sec)) | ||||
| 		return 1; | ||||
| 	fprintf(stderr, "TIME ERROR!!\n"); | ||||
| 	fprintf(stderr, "Time1: %d/%d/%d, %d:%02d:%02d\n", | ||||
| 			tm2.tm_mday, tm2.tm_mon + 1, tm2.tm_year + 1900, | ||||
| 			tm2.tm_hour, tm2.tm_min, tm2.tm_sec); | ||||
| 	fprintf(stderr, "Time2: %d/%d/%d, %d:%02d:%02d\n", | ||||
| 			tm1.tm_mday, tm1.tm_mon + 1, tm1.tm_year + 1900, | ||||
| 			tm1.tm_hour, tm1.tm_min, tm1.tm_sec); | ||||
| 	return 0; | ||||
| 	} | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -62,5 +62,6 @@ | |||
| #include <time.h> | ||||
| 
 | ||||
| struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result); | ||||
| int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -767,6 +767,8 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne); | |||
| int		X509_cmp_time(const ASN1_TIME *s, time_t *t); | ||||
| int		X509_cmp_current_time(const ASN1_TIME *s); | ||||
| ASN1_TIME *	X509_time_adj(ASN1_TIME *s, long adj, time_t *t); | ||||
| ASN1_TIME *	X509_time_adj_ex(ASN1_TIME *s, | ||||
| 				int offset_day, long offset_sec, time_t *t); | ||||
| ASN1_TIME *	X509_gmtime_adj(ASN1_TIME *s, long adj); | ||||
| 
 | ||||
| const char *	X509_get_default_cert_area(void ); | ||||
|  |  | |||
|  | @ -1752,7 +1752,13 @@ ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj) | |||
| 	return X509_time_adj(s, adj, NULL); | ||||
| } | ||||
| 
 | ||||
| ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm) | ||||
| ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm) | ||||
| 	{ | ||||
| 	return X509_time_adj_ex(s, 0, offset_sec, in_tm); | ||||
| 	} | ||||
| 
 | ||||
| ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, | ||||
| 				int offset_day, long offset_sec, time_t *in_tm) | ||||
| 	{ | ||||
| 	time_t t; | ||||
| 	int type = -1; | ||||
|  | @ -1760,11 +1766,12 @@ ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm) | |||
| 	if (in_tm) t = *in_tm; | ||||
| 	else time(&t); | ||||
| 
 | ||||
| 	t+=adj; | ||||
| 	if (s) type = s->type; | ||||
| 	if (type == V_ASN1_UTCTIME) return ASN1_UTCTIME_set(s,t); | ||||
| 	if (type == V_ASN1_GENERALIZEDTIME) return ASN1_GENERALIZEDTIME_set(s, t); | ||||
| 	return ASN1_TIME_set(s, t); | ||||
| 	if (type == V_ASN1_UTCTIME) | ||||
| 		return ASN1_UTCTIME_adj(s,t, offset_day, offset_sec); | ||||
| 	if (type == V_ASN1_GENERALIZEDTIME) | ||||
| 		return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); | ||||
| 	return ASN1_TIME_adj(s, t, offset_day, offset_sec); | ||||
| 	} | ||||
| 
 | ||||
| int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue