155714Skris/* crypto/asn1/a_utctm.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296465Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296465Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296465Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296465Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296465Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <time.h>
6155714Skris#include "cryptlib.h"
62109998Smarkm#include "o_time.h"
6355714Skris#include <openssl/asn1.h>
6455714Skris
65109998Smarkm#if 0
6655714Skrisint i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
67296465Sdelphij{
68296465Sdelphij# ifndef CHARSET_EBCDIC
69296465Sdelphij    return (i2d_ASN1_bytes((ASN1_STRING *)a, pp,
70296465Sdelphij                           V_ASN1_UTCTIME, V_ASN1_UNIVERSAL));
71296465Sdelphij# else
72296465Sdelphij    /* KLUDGE! We convert to ascii before writing DER */
73296465Sdelphij    int len;
74296465Sdelphij    char tmp[24];
75296465Sdelphij    ASN1_STRING x = *(ASN1_STRING *)a;
7655714Skris
77296465Sdelphij    len = x.length;
78296465Sdelphij    ebcdic2ascii(tmp, x.data, (len >= sizeof tmp) ? sizeof tmp : len);
79296465Sdelphij    x.data = tmp;
80296465Sdelphij    return i2d_ASN1_bytes(&x, pp, V_ASN1_UTCTIME, V_ASN1_UNIVERSAL);
81296465Sdelphij# endif
82296465Sdelphij}
8355714Skris
8455714SkrisASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, unsigned char **pp,
85296465Sdelphij                               long length)
86296465Sdelphij{
87296465Sdelphij    ASN1_UTCTIME *ret = NULL;
8855714Skris
89296465Sdelphij    ret = (ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a, pp, length,
90296465Sdelphij                                         V_ASN1_UTCTIME, V_ASN1_UNIVERSAL);
91296465Sdelphij    if (ret == NULL) {
92296465Sdelphij        ASN1err(ASN1_F_D2I_ASN1_UTCTIME, ERR_R_NESTED_ASN1_ERROR);
93296465Sdelphij        return (NULL);
94296465Sdelphij    }
95296465Sdelphij# ifdef CHARSET_EBCDIC
96296465Sdelphij    ascii2ebcdic(ret->data, ret->data, ret->length);
97296465Sdelphij# endif
98296465Sdelphij    if (!ASN1_UTCTIME_check(ret)) {
99296465Sdelphij        ASN1err(ASN1_F_D2I_ASN1_UTCTIME, ASN1_R_INVALID_TIME_FORMAT);
100296465Sdelphij        goto err;
101296465Sdelphij    }
10255714Skris
103296465Sdelphij    return (ret);
104296465Sdelphij err:
105296465Sdelphij    if ((ret != NULL) && ((a == NULL) || (*a != ret)))
106296465Sdelphij        M_ASN1_UTCTIME_free(ret);
107296465Sdelphij    return (NULL);
108296465Sdelphij}
10955714Skris
110109998Smarkm#endif
111109998Smarkm
11255714Skrisint ASN1_UTCTIME_check(ASN1_UTCTIME *d)
113296465Sdelphij{
114296465Sdelphij    static int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
115296465Sdelphij    static int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
116296465Sdelphij    char *a;
117296465Sdelphij    int n, i, l, o;
11855714Skris
119296465Sdelphij    if (d->type != V_ASN1_UTCTIME)
120296465Sdelphij        return (0);
121296465Sdelphij    l = d->length;
122296465Sdelphij    a = (char *)d->data;
123296465Sdelphij    o = 0;
12455714Skris
125296465Sdelphij    if (l < 11)
126296465Sdelphij        goto err;
127296465Sdelphij    for (i = 0; i < 6; i++) {
128296465Sdelphij        if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
129296465Sdelphij            i++;
130296465Sdelphij            break;
131296465Sdelphij        }
132296465Sdelphij        if ((a[o] < '0') || (a[o] > '9'))
133296465Sdelphij            goto err;
134296465Sdelphij        n = a[o] - '0';
135296465Sdelphij        if (++o > l)
136296465Sdelphij            goto err;
13755714Skris
138296465Sdelphij        if ((a[o] < '0') || (a[o] > '9'))
139296465Sdelphij            goto err;
140296465Sdelphij        n = (n * 10) + a[o] - '0';
141296465Sdelphij        if (++o > l)
142296465Sdelphij            goto err;
14355714Skris
144296465Sdelphij        if ((n < min[i]) || (n > max[i]))
145296465Sdelphij            goto err;
146296465Sdelphij    }
147296465Sdelphij    if (a[o] == 'Z')
148296465Sdelphij        o++;
149296465Sdelphij    else if ((a[o] == '+') || (a[o] == '-')) {
150296465Sdelphij        o++;
151296465Sdelphij        if (o + 4 > l)
152296465Sdelphij            goto err;
153296465Sdelphij        for (i = 6; i < 8; i++) {
154296465Sdelphij            if ((a[o] < '0') || (a[o] > '9'))
155296465Sdelphij                goto err;
156296465Sdelphij            n = a[o] - '0';
157296465Sdelphij            o++;
158296465Sdelphij            if ((a[o] < '0') || (a[o] > '9'))
159296465Sdelphij                goto err;
160296465Sdelphij            n = (n * 10) + a[o] - '0';
161296465Sdelphij            if ((n < min[i]) || (n > max[i]))
162296465Sdelphij                goto err;
163296465Sdelphij            o++;
164296465Sdelphij        }
165296465Sdelphij    }
166296465Sdelphij    return (o == l);
167296465Sdelphij err:
168296465Sdelphij    return (0);
169296465Sdelphij}
17055714Skris
171160814Ssimonint ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
172296465Sdelphij{
173296465Sdelphij    ASN1_UTCTIME t;
17455714Skris
175296465Sdelphij    t.type = V_ASN1_UTCTIME;
176296465Sdelphij    t.length = strlen(str);
177296465Sdelphij    t.data = (unsigned char *)str;
178296465Sdelphij    if (ASN1_UTCTIME_check(&t)) {
179296465Sdelphij        if (s != NULL) {
180296465Sdelphij            if (!ASN1_STRING_set((ASN1_STRING *)s,
181296465Sdelphij                                 (unsigned char *)str, t.length))
182296465Sdelphij                return 0;
183296465Sdelphij            s->type = V_ASN1_UTCTIME;
184296465Sdelphij        }
185296465Sdelphij        return (1);
186296465Sdelphij    } else
187296465Sdelphij        return (0);
188296465Sdelphij}
18955714Skris
19055714SkrisASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
191296465Sdelphij{
192296465Sdelphij    char *p;
193296465Sdelphij    struct tm *ts;
194296465Sdelphij    struct tm data;
195296465Sdelphij    size_t len = 20;
19655714Skris
197296465Sdelphij    if (s == NULL)
198296465Sdelphij        s = M_ASN1_UTCTIME_new();
199296465Sdelphij    if (s == NULL)
200296465Sdelphij        return (NULL);
20155714Skris
202296465Sdelphij    ts = OPENSSL_gmtime(&t, &data);
203296465Sdelphij    if (ts == NULL)
204296465Sdelphij        return (NULL);
20555714Skris
206296465Sdelphij    p = (char *)s->data;
207296465Sdelphij    if ((p == NULL) || ((size_t)s->length < len)) {
208296465Sdelphij        p = OPENSSL_malloc(len);
209296465Sdelphij        if (p == NULL) {
210296465Sdelphij            ASN1err(ASN1_F_ASN1_UTCTIME_SET, ERR_R_MALLOC_FAILURE);
211296465Sdelphij            return (NULL);
212296465Sdelphij        }
213296465Sdelphij        if (s->data != NULL)
214296465Sdelphij            OPENSSL_free(s->data);
215296465Sdelphij        s->data = (unsigned char *)p;
216296465Sdelphij    }
21755714Skris
218296465Sdelphij    BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
219296465Sdelphij                 ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
220296465Sdelphij                 ts->tm_sec);
221296465Sdelphij    s->length = strlen(p);
222296465Sdelphij    s->type = V_ASN1_UTCTIME;
22355714Skris#ifdef CHARSET_EBCDIC_not
224296465Sdelphij    ebcdic2ascii(s->data, s->data, s->length);
22555714Skris#endif
226296465Sdelphij    return (s);
227296465Sdelphij}
22868651Skris
22968651Skrisint ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
230296465Sdelphij{
231296465Sdelphij    struct tm *tm;
232296465Sdelphij    struct tm data;
233296465Sdelphij    int offset;
234296465Sdelphij    int year;
23568651Skris
23668651Skris#define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
23768651Skris
238296465Sdelphij    if (s->data[12] == 'Z')
239296465Sdelphij        offset = 0;
240296465Sdelphij    else {
241296465Sdelphij        offset = g2(s->data + 13) * 60 + g2(s->data + 15);
242296465Sdelphij        if (s->data[12] == '-')
243296465Sdelphij            offset = -offset;
244296465Sdelphij    }
24568651Skris
246296465Sdelphij    t -= offset * 60;           /* FIXME: may overflow in extreme cases */
24768651Skris
248296465Sdelphij    tm = OPENSSL_gmtime(&t, &data);
249296465Sdelphij
25068651Skris#define return_cmp(a,b) if ((a)<(b)) return -1; else if ((a)>(b)) return 1
251296465Sdelphij    year = g2(s->data);
252296465Sdelphij    if (year < 50)
253296465Sdelphij        year += 100;
254296465Sdelphij    return_cmp(year, tm->tm_year);
255296465Sdelphij    return_cmp(g2(s->data + 2) - 1, tm->tm_mon);
256296465Sdelphij    return_cmp(g2(s->data + 4), tm->tm_mday);
257296465Sdelphij    return_cmp(g2(s->data + 6), tm->tm_hour);
258296465Sdelphij    return_cmp(g2(s->data + 8), tm->tm_min);
259296465Sdelphij    return_cmp(g2(s->data + 10), tm->tm_sec);
26068651Skris#undef g2
26168651Skris#undef return_cmp
26268651Skris
263296465Sdelphij    return 0;
264296465Sdelphij}
26568651Skris
26668651Skris#if 0
26768651Skristime_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
268296465Sdelphij{
269296465Sdelphij    struct tm tm;
270296465Sdelphij    int offset;
27168651Skris
272296465Sdelphij    memset(&tm, '\0', sizeof tm);
27368651Skris
274296465Sdelphij# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
275296465Sdelphij    tm.tm_year = g2(s->data);
276296465Sdelphij    if (tm.tm_year < 50)
277296465Sdelphij        tm.tm_year += 100;
278296465Sdelphij    tm.tm_mon = g2(s->data + 2) - 1;
279296465Sdelphij    tm.tm_mday = g2(s->data + 4);
280296465Sdelphij    tm.tm_hour = g2(s->data + 6);
281296465Sdelphij    tm.tm_min = g2(s->data + 8);
282296465Sdelphij    tm.tm_sec = g2(s->data + 10);
283296465Sdelphij    if (s->data[12] == 'Z')
284296465Sdelphij        offset = 0;
285296465Sdelphij    else {
286296465Sdelphij        offset = g2(s->data + 13) * 60 + g2(s->data + 15);
287296465Sdelphij        if (s->data[12] == '-')
288296465Sdelphij            offset = -offset;
289296465Sdelphij    }
290296465Sdelphij# undef g2
29168651Skris
292296465Sdelphij    /*
293296465Sdelphij     * FIXME: mktime assumes the current timezone
294296465Sdelphij     * instead of UTC, and unless we rewrite OpenSSL
295296465Sdelphij     * in Lisp we cannot locally change the timezone
296296465Sdelphij     * without possibly interfering with other parts
297296465Sdelphij     * of the program. timegm, which uses UTC, is
298296465Sdelphij     * non-standard.
299296465Sdelphij     * Also time_t is inappropriate for general
300296465Sdelphij     * UTC times because it may a 32 bit type.
301296465Sdelphij     */
302296465Sdelphij    return mktime(&tm) - offset * 60;
303296465Sdelphij}
30468651Skris#endif
305