xref: /onnv-gate/usr/src/common/openssl/crypto/asn1/a_utctm.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* crypto/asn1/a_utctm.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate  * All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * This package is an SSL implementation written
60Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
110Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate  * the code are not to be removed.
180Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate  * as the author of the parts of the library used.
200Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate  * are met:
260Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate  *    must display the following acknowledgement:
330Sstevel@tonic-gate  *    "This product includes cryptographic software written by
340Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate  *    being used are not cryptographic related :-).
370Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate  * SUCH DAMAGE.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
550Sstevel@tonic-gate  * copied and put under another distribution licence
560Sstevel@tonic-gate  * [including the GNU Public Licence.]
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include <time.h>
610Sstevel@tonic-gate #include "cryptlib.h"
620Sstevel@tonic-gate #include "o_time.h"
630Sstevel@tonic-gate #include <openssl/asn1.h>
640Sstevel@tonic-gate 
650Sstevel@tonic-gate #if 0
660Sstevel@tonic-gate int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
670Sstevel@tonic-gate 	{
680Sstevel@tonic-gate #ifndef CHARSET_EBCDIC
690Sstevel@tonic-gate 	return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
700Sstevel@tonic-gate 		V_ASN1_UTCTIME,V_ASN1_UNIVERSAL));
710Sstevel@tonic-gate #else
720Sstevel@tonic-gate 	/* KLUDGE! We convert to ascii before writing DER */
730Sstevel@tonic-gate 	int len;
740Sstevel@tonic-gate 	char tmp[24];
750Sstevel@tonic-gate 	ASN1_STRING x = *(ASN1_STRING *)a;
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	len = x.length;
780Sstevel@tonic-gate 	ebcdic2ascii(tmp, x.data, (len >= sizeof tmp) ? sizeof tmp : len);
790Sstevel@tonic-gate 	x.data = tmp;
800Sstevel@tonic-gate 	return i2d_ASN1_bytes(&x, pp, V_ASN1_UTCTIME,V_ASN1_UNIVERSAL);
810Sstevel@tonic-gate #endif
820Sstevel@tonic-gate 	}
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 
850Sstevel@tonic-gate ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, unsigned char **pp,
860Sstevel@tonic-gate 	     long length)
870Sstevel@tonic-gate 	{
880Sstevel@tonic-gate 	ASN1_UTCTIME *ret=NULL;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	ret=(ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a,pp,length,
910Sstevel@tonic-gate 		V_ASN1_UTCTIME,V_ASN1_UNIVERSAL);
920Sstevel@tonic-gate 	if (ret == NULL)
930Sstevel@tonic-gate 		{
940Sstevel@tonic-gate 		ASN1err(ASN1_F_D2I_ASN1_UTCTIME,ERR_R_NESTED_ASN1_ERROR);
950Sstevel@tonic-gate 		return(NULL);
960Sstevel@tonic-gate 		}
970Sstevel@tonic-gate #ifdef CHARSET_EBCDIC
980Sstevel@tonic-gate 	ascii2ebcdic(ret->data, ret->data, ret->length);
990Sstevel@tonic-gate #endif
1000Sstevel@tonic-gate 	if (!ASN1_UTCTIME_check(ret))
1010Sstevel@tonic-gate 		{
1020Sstevel@tonic-gate 		ASN1err(ASN1_F_D2I_ASN1_UTCTIME,ASN1_R_INVALID_TIME_FORMAT);
1030Sstevel@tonic-gate 		goto err;
1040Sstevel@tonic-gate 		}
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	return(ret);
1070Sstevel@tonic-gate err:
1080Sstevel@tonic-gate 	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
1090Sstevel@tonic-gate 		M_ASN1_UTCTIME_free(ret);
1100Sstevel@tonic-gate 	return(NULL);
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate #endif
1140Sstevel@tonic-gate 
ASN1_UTCTIME_check(ASN1_UTCTIME * d)1150Sstevel@tonic-gate int ASN1_UTCTIME_check(ASN1_UTCTIME *d)
1160Sstevel@tonic-gate 	{
1170Sstevel@tonic-gate 	static int min[8]={ 0, 1, 1, 0, 0, 0, 0, 0};
1180Sstevel@tonic-gate 	static int max[8]={99,12,31,23,59,59,12,59};
1190Sstevel@tonic-gate 	char *a;
1200Sstevel@tonic-gate 	int n,i,l,o;
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 	if (d->type != V_ASN1_UTCTIME) return(0);
1230Sstevel@tonic-gate 	l=d->length;
1240Sstevel@tonic-gate 	a=(char *)d->data;
1250Sstevel@tonic-gate 	o=0;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	if (l < 11) goto err;
1280Sstevel@tonic-gate 	for (i=0; i<6; i++)
1290Sstevel@tonic-gate 		{
1300Sstevel@tonic-gate 		if ((i == 5) && ((a[o] == 'Z') ||
1310Sstevel@tonic-gate 			(a[o] == '+') || (a[o] == '-')))
1320Sstevel@tonic-gate 			{ i++; break; }
1330Sstevel@tonic-gate 		if ((a[o] < '0') || (a[o] > '9')) goto err;
1340Sstevel@tonic-gate 		n= a[o]-'0';
1350Sstevel@tonic-gate 		if (++o > l) goto err;
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 		if ((a[o] < '0') || (a[o] > '9')) goto err;
1380Sstevel@tonic-gate 		n=(n*10)+ a[o]-'0';
1390Sstevel@tonic-gate 		if (++o > l) goto err;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 		if ((n < min[i]) || (n > max[i])) goto err;
1420Sstevel@tonic-gate 		}
1430Sstevel@tonic-gate 	if (a[o] == 'Z')
1440Sstevel@tonic-gate 		o++;
1450Sstevel@tonic-gate 	else if ((a[o] == '+') || (a[o] == '-'))
1460Sstevel@tonic-gate 		{
1470Sstevel@tonic-gate 		o++;
1480Sstevel@tonic-gate 		if (o+4 > l) goto err;
1490Sstevel@tonic-gate 		for (i=6; i<8; i++)
1500Sstevel@tonic-gate 			{
1510Sstevel@tonic-gate 			if ((a[o] < '0') || (a[o] > '9')) goto err;
1520Sstevel@tonic-gate 			n= a[o]-'0';
1530Sstevel@tonic-gate 			o++;
1540Sstevel@tonic-gate 			if ((a[o] < '0') || (a[o] > '9')) goto err;
1550Sstevel@tonic-gate 			n=(n*10)+ a[o]-'0';
1560Sstevel@tonic-gate 			if ((n < min[i]) || (n > max[i])) goto err;
1570Sstevel@tonic-gate 			o++;
1580Sstevel@tonic-gate 			}
1590Sstevel@tonic-gate 		}
1600Sstevel@tonic-gate 	return(o == l);
1610Sstevel@tonic-gate err:
1620Sstevel@tonic-gate 	return(0);
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 
ASN1_UTCTIME_set_string(ASN1_UTCTIME * s,const char * str)165*2139Sjp161948 int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
1660Sstevel@tonic-gate 	{
1670Sstevel@tonic-gate 	ASN1_UTCTIME t;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	t.type=V_ASN1_UTCTIME;
1700Sstevel@tonic-gate 	t.length=strlen(str);
1710Sstevel@tonic-gate 	t.data=(unsigned char *)str;
1720Sstevel@tonic-gate 	if (ASN1_UTCTIME_check(&t))
1730Sstevel@tonic-gate 		{
1740Sstevel@tonic-gate 		if (s != NULL)
1750Sstevel@tonic-gate 			{
176*2139Sjp161948 			if (!ASN1_STRING_set((ASN1_STRING *)s,
177*2139Sjp161948 				(unsigned char *)str,t.length))
178*2139Sjp161948 				return 0;
1790Sstevel@tonic-gate 			s->type = V_ASN1_UTCTIME;
1800Sstevel@tonic-gate 			}
1810Sstevel@tonic-gate 		return(1);
1820Sstevel@tonic-gate 		}
1830Sstevel@tonic-gate 	else
1840Sstevel@tonic-gate 		return(0);
1850Sstevel@tonic-gate 	}
1860Sstevel@tonic-gate 
ASN1_UTCTIME_set(ASN1_UTCTIME * s,time_t t)1870Sstevel@tonic-gate ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
1880Sstevel@tonic-gate 	{
1890Sstevel@tonic-gate 	char *p;
1900Sstevel@tonic-gate 	struct tm *ts;
1910Sstevel@tonic-gate 	struct tm data;
1920Sstevel@tonic-gate 	size_t len = 20;
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	if (s == NULL)
1950Sstevel@tonic-gate 		s=M_ASN1_UTCTIME_new();
1960Sstevel@tonic-gate 	if (s == NULL)
1970Sstevel@tonic-gate 		return(NULL);
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	ts=OPENSSL_gmtime(&t, &data);
2000Sstevel@tonic-gate 	if (ts == NULL)
2010Sstevel@tonic-gate 		return(NULL);
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	p=(char *)s->data;
2040Sstevel@tonic-gate 	if ((p == NULL) || ((size_t)s->length < len))
2050Sstevel@tonic-gate 		{
2060Sstevel@tonic-gate 		p=OPENSSL_malloc(len);
207*2139Sjp161948 		if (p == NULL)
208*2139Sjp161948 			{
209*2139Sjp161948 			ASN1err(ASN1_F_ASN1_UTCTIME_SET,ERR_R_MALLOC_FAILURE);
210*2139Sjp161948 			return(NULL);
211*2139Sjp161948 			}
2120Sstevel@tonic-gate 		if (s->data != NULL)
2130Sstevel@tonic-gate 			OPENSSL_free(s->data);
2140Sstevel@tonic-gate 		s->data=(unsigned char *)p;
2150Sstevel@tonic-gate 		}
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	BIO_snprintf(p,len,"%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100,
2180Sstevel@tonic-gate 		     ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
2190Sstevel@tonic-gate 	s->length=strlen(p);
2200Sstevel@tonic-gate 	s->type=V_ASN1_UTCTIME;
2210Sstevel@tonic-gate #ifdef CHARSET_EBCDIC_not
2220Sstevel@tonic-gate 	ebcdic2ascii(s->data, s->data, s->length);
2230Sstevel@tonic-gate #endif
2240Sstevel@tonic-gate 	return(s);
2250Sstevel@tonic-gate 	}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 
ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME * s,time_t t)2280Sstevel@tonic-gate int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
2290Sstevel@tonic-gate 	{
2300Sstevel@tonic-gate 	struct tm *tm;
2310Sstevel@tonic-gate 	struct tm data;
2320Sstevel@tonic-gate 	int offset;
2330Sstevel@tonic-gate 	int year;
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate #define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	if (s->data[12] == 'Z')
2380Sstevel@tonic-gate 		offset=0;
2390Sstevel@tonic-gate 	else
2400Sstevel@tonic-gate 		{
2410Sstevel@tonic-gate 		offset = g2(s->data+13)*60+g2(s->data+15);
2420Sstevel@tonic-gate 		if (s->data[12] == '-')
2430Sstevel@tonic-gate 			offset = -offset;
2440Sstevel@tonic-gate 		}
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	t -= offset*60; /* FIXME: may overflow in extreme cases */
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	tm = OPENSSL_gmtime(&t, &data);
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate #define return_cmp(a,b) if ((a)<(b)) return -1; else if ((a)>(b)) return 1
2510Sstevel@tonic-gate 	year = g2(s->data);
2520Sstevel@tonic-gate 	if (year < 50)
2530Sstevel@tonic-gate 		year += 100;
2540Sstevel@tonic-gate 	return_cmp(year,              tm->tm_year);
2550Sstevel@tonic-gate 	return_cmp(g2(s->data+2) - 1, tm->tm_mon);
2560Sstevel@tonic-gate 	return_cmp(g2(s->data+4),     tm->tm_mday);
2570Sstevel@tonic-gate 	return_cmp(g2(s->data+6),     tm->tm_hour);
2580Sstevel@tonic-gate 	return_cmp(g2(s->data+8),     tm->tm_min);
2590Sstevel@tonic-gate 	return_cmp(g2(s->data+10),    tm->tm_sec);
2600Sstevel@tonic-gate #undef g2
2610Sstevel@tonic-gate #undef return_cmp
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	return 0;
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate #if 0
2680Sstevel@tonic-gate time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
2690Sstevel@tonic-gate 	{
2700Sstevel@tonic-gate 	struct tm tm;
2710Sstevel@tonic-gate 	int offset;
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	memset(&tm,'\0',sizeof tm);
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate #define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
2760Sstevel@tonic-gate 	tm.tm_year=g2(s->data);
2770Sstevel@tonic-gate 	if(tm.tm_year < 50)
2780Sstevel@tonic-gate 		tm.tm_year+=100;
2790Sstevel@tonic-gate 	tm.tm_mon=g2(s->data+2)-1;
2800Sstevel@tonic-gate 	tm.tm_mday=g2(s->data+4);
2810Sstevel@tonic-gate 	tm.tm_hour=g2(s->data+6);
2820Sstevel@tonic-gate 	tm.tm_min=g2(s->data+8);
2830Sstevel@tonic-gate 	tm.tm_sec=g2(s->data+10);
2840Sstevel@tonic-gate 	if(s->data[12] == 'Z')
2850Sstevel@tonic-gate 		offset=0;
2860Sstevel@tonic-gate 	else
2870Sstevel@tonic-gate 		{
2880Sstevel@tonic-gate 		offset=g2(s->data+13)*60+g2(s->data+15);
2890Sstevel@tonic-gate 		if(s->data[12] == '-')
2900Sstevel@tonic-gate 			offset= -offset;
2910Sstevel@tonic-gate 		}
2920Sstevel@tonic-gate #undef g2
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	return mktime(&tm)-offset*60; /* FIXME: mktime assumes the current timezone
2950Sstevel@tonic-gate 	                               * instead of UTC, and unless we rewrite OpenSSL
2960Sstevel@tonic-gate 				       * in Lisp we cannot locally change the timezone
2970Sstevel@tonic-gate 				       * without possibly interfering with other parts
2980Sstevel@tonic-gate 	                               * of the program. timegm, which uses UTC, is
2990Sstevel@tonic-gate 				       * non-standard.
3000Sstevel@tonic-gate 	                               * Also time_t is inappropriate for general
3010Sstevel@tonic-gate 	                               * UTC times because it may a 32 bit type. */
3020Sstevel@tonic-gate 	}
3030Sstevel@tonic-gate #endif
304