Make string_to_hex/hex_to_string public
[openssl.git] / crypto / asn1 / a_time.c
1 /* ====================================================================
2  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the OpenSSL Project
19  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    licensing@OpenSSL.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  *    nor may "OpenSSL" appear in their names without prior written
28  *    permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the OpenSSL Project
33  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This product includes cryptographic software written by Eric Young
50  * (eay@cryptsoft.com).  This product includes software written by Tim
51  * Hudson (tjh@cryptsoft.com).
52  *
53  */
54
55 /*-
56  * This is an implementation of the ASN1 Time structure which is:
57  *    Time ::= CHOICE {
58  *      utcTime        UTCTime,
59  *      generalTime    GeneralizedTime }
60  * written by Steve Henson.
61  */
62
63 #include <stdio.h>
64 #include <time.h>
65 #include "internal/cryptlib.h"
66 #include <openssl/asn1t.h>
67 #include "asn1_locl.h"
68
69 IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
70
71 IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
72
73 ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
74 {
75     return ASN1_TIME_adj(s, t, 0, 0);
76 }
77
78 ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
79                          int offset_day, long offset_sec)
80 {
81     struct tm *ts;
82     struct tm data;
83
84     ts = OPENSSL_gmtime(&t, &data);
85     if (ts == NULL) {
86         ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME);
87         return NULL;
88     }
89     if (offset_day || offset_sec) {
90         if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
91             return NULL;
92     }
93     if ((ts->tm_year >= 50) && (ts->tm_year < 150))
94         return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
95     return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
96 }
97
98 int ASN1_TIME_check(const ASN1_TIME *t)
99 {
100     if (t->type == V_ASN1_GENERALIZEDTIME)
101         return ASN1_GENERALIZEDTIME_check(t);
102     else if (t->type == V_ASN1_UTCTIME)
103         return ASN1_UTCTIME_check(t);
104     return 0;
105 }
106
107 /* Convert an ASN1_TIME structure to GeneralizedTime */
108 ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
109                                                    ASN1_GENERALIZEDTIME **out)
110 {
111     ASN1_GENERALIZEDTIME *ret;
112     char *str;
113     int newlen;
114
115     if (!ASN1_TIME_check(t))
116         return NULL;
117
118     if (out == NULL || *out == NULL) {
119         if ((ret = ASN1_GENERALIZEDTIME_new()) == NULL)
120             return NULL;
121         if (out)
122             *out = ret;
123     } else
124         ret = *out;
125
126     /* If already GeneralizedTime just copy across */
127     if (t->type == V_ASN1_GENERALIZEDTIME) {
128         if (!ASN1_STRING_set(ret, t->data, t->length))
129             return NULL;
130         return ret;
131     }
132
133     /* grow the string */
134     if (!ASN1_STRING_set(ret, NULL, t->length + 2))
135         return NULL;
136     /* ASN1_STRING_set() allocated 'len + 1' bytes. */
137     newlen = t->length + 2 + 1;
138     str = (char *)ret->data;
139     /* Work out the century and prepend */
140     if (t->data[0] >= '5')
141         OPENSSL_strlcpy(str, "19", newlen);
142     else
143         OPENSSL_strlcpy(str, "20", newlen);
144
145     OPENSSL_strlcat(str, (char *)t->data, newlen);
146
147     return ret;
148 }
149
150 int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
151 {
152     ASN1_TIME t;
153
154     t.length = strlen(str);
155     t.data = (unsigned char *)str;
156     t.flags = 0;
157
158     t.type = V_ASN1_UTCTIME;
159
160     if (!ASN1_TIME_check(&t)) {
161         t.type = V_ASN1_GENERALIZEDTIME;
162         if (!ASN1_TIME_check(&t))
163             return 0;
164     }
165
166     if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
167         return 0;
168
169     return 1;
170 }
171
172 static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
173 {
174     if (t == NULL) {
175         time_t now_t;
176         time(&now_t);
177         if (OPENSSL_gmtime(&now_t, tm))
178             return 1;
179         return 0;
180     }
181
182     if (t->type == V_ASN1_UTCTIME)
183         return asn1_utctime_to_tm(tm, t);
184     else if (t->type == V_ASN1_GENERALIZEDTIME)
185         return asn1_generalizedtime_to_tm(tm, t);
186
187     return 0;
188 }
189
190 int ASN1_TIME_diff(int *pday, int *psec,
191                    const ASN1_TIME *from, const ASN1_TIME *to)
192 {
193     struct tm tm_from, tm_to;
194     if (!asn1_time_to_tm(&tm_from, from))
195         return 0;
196     if (!asn1_time_to_tm(&tm_to, to))
197         return 0;
198     return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
199 }
200
201 int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
202 {
203     if (tm->type == V_ASN1_UTCTIME)
204         return ASN1_UTCTIME_print(bp, tm);
205     if (tm->type == V_ASN1_GENERALIZEDTIME)
206         return ASN1_GENERALIZEDTIME_print(bp, tm);
207     BIO_write(bp, "Bad time value", 14);
208     return (0);
209 }