X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fasn1%2Fa_time.c;h=7036868fcc110a1cda653bcb2f699541911f0f65;hp=c19b7b2cac58a1272b3a852f374c31a2f5ca533a;hb=84917787b5a3df5b9077a9b8bca38f7ed65dd7b5;hpb=ce0d9f049a1cc054aec0c4da627156aee74b1d76;ds=sidebyside diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index c19b7b2cac..7036868fcc 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -64,45 +64,165 @@ #include #include #include "cryptlib.h" -#include +#include +#include "asn1_locl.h" +IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) + +IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) + +#if 0 int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp) { +#ifdef CHARSET_EBCDIC + /* KLUDGE! We convert to ascii before writing DER */ + char tmp[24]; + ASN1_STRING tmpstr; + + if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME) { + int len; + + tmpstr = *(ASN1_STRING *)a; + len = tmpstr.length; + ebcdic2ascii(tmp, tmpstr.data, (len >= sizeof tmp) ? sizeof tmp : len); + tmpstr.data = tmp; + a = (ASN1_GENERALIZEDTIME *) &tmpstr; + } +#endif if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME) return(i2d_ASN1_bytes((ASN1_STRING *)a,pp, a->type ,V_ASN1_UNIVERSAL)); ASN1err(ASN1_F_I2D_ASN1_TIME,ASN1_R_EXPECTING_A_TIME); return -1; } +#endif -ASN1_TIME *d2i_ASN1_TIME(ASN1_TIME **a, unsigned char **pp, long length) +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) { - unsigned char tag; - tag = **pp & ~V_ASN1_CONSTRUCTED; - if(tag == (V_ASN1_UTCTIME|V_ASN1_UNIVERSAL)) - return d2i_ASN1_UTCTIME(a, pp, length); - if(tag == (V_ASN1_GENERALIZEDTIME|V_ASN1_UNIVERSAL)) - return d2i_ASN1_GENERALIZEDTIME(a, pp, length); - ASN1err(ASN1_F_D2I_ASN1_TIME,ASN1_R_EXPECTING_A_TIME); - return(NULL); + return ASN1_TIME_adj(s, t, 0, 0); } - -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) { struct tm *ts; -#if defined(THREADS) && !defined(WIN32) struct tm data; -#endif -#if defined(THREADS) && !defined(WIN32) - gmtime_r(&t,&data); - ts=&data; /* should return &data, but doesn't on some systems, so we don't even look at the return value */ -#else - ts=gmtime(&t); -#endif - if((ts->tm_year >= 1950) && (ts->tm_year < 2050)) - return ASN1_UTCTIME_set(s, t); - return ASN1_GENERALIZEDTIME_set(s,t); + ts=OPENSSL_gmtime(&t,&data); + if (ts == NULL) + { + ASN1err(ASN1_F_ASN1_TIME_ADJ, 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_adj(s, t, offset_day, offset_sec); + return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); + } + +int ASN1_TIME_check(const ASN1_TIME *t) + { + if (t->type == V_ASN1_GENERALIZEDTIME) + return ASN1_GENERALIZEDTIME_check(t); + else if (t->type == V_ASN1_UTCTIME) + return ASN1_UTCTIME_check(t); + return 0; + } + +/* Convert an ASN1_TIME structure to GeneralizedTime */ +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) + { + ASN1_GENERALIZEDTIME *ret; + char *str; + int newlen; + + if (!ASN1_TIME_check(t)) return NULL; + + if (!out || !*out) + { + if (!(ret = ASN1_GENERALIZEDTIME_new ())) + return NULL; + if (out) *out = ret; + } + else ret = *out; + + /* If already GeneralizedTime just copy across */ + if (t->type == V_ASN1_GENERALIZEDTIME) + { + if(!ASN1_STRING_set(ret, t->data, t->length)) + return NULL; + return ret; + } + + /* grow the string */ + if (!ASN1_STRING_set(ret, NULL, t->length + 2)) + return NULL; + /* ASN1_STRING_set() allocated 'len + 1' bytes. */ + newlen = t->length + 2 + 1; + str = (char *)ret->data; + /* Work out the century and prepend */ + if (t->data[0] >= '5') BUF_strlcpy(str, "19", newlen); + else BUF_strlcpy(str, "20", newlen); + + BUF_strlcat(str, (char *)t->data, newlen); + + return ret; + } + +int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) + { + ASN1_TIME t; + + t.length = strlen(str); + t.data = (unsigned char *)str; + t.flags = 0; + + t.type = V_ASN1_UTCTIME; + + if (!ASN1_TIME_check(&t)) + { + t.type = V_ASN1_GENERALIZEDTIME; + if (!ASN1_TIME_check(&t)) + return 0; + } + + if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) + return 0; + + return 1; } + +static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t) + { + if (t == NULL) + { + time_t now_t; + time(&now_t); + if (OPENSSL_gmtime(&now_t, tm)) + return 1; + return 0; + } + + if (t->type == V_ASN1_UTCTIME) + return asn1_utctime_to_tm(tm, t); + else if (t->type == V_ASN1_GENERALIZEDTIME) + return asn1_generalizedtime_to_tm(tm, t); + + return 0; + } + +int ASN1_TIME_diff(int *pday, int *psec, + const ASN1_TIME *from, const ASN1_TIME *to) + { + struct tm tm_from, tm_to; + if (!asn1_time_to_tm(&tm_from, from)) + return 0; + if (!asn1_time_to_tm(&tm_to, to)) + return 0; + return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to); + }