1 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
2 | * All rights reserved. |
3 | * |
4 | * This package is an SSL implementation written |
5 | * by Eric Young (eay@cryptsoft.com). |
6 | * The implementation was written so as to conform with Netscapes SSL. |
7 | * |
8 | * This library is free for commercial and non-commercial use as long as |
9 | * the following conditions are aheared to. The following conditions |
10 | * apply to all code found in this distribution, be it the RC4, RSA, |
11 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
12 | * included with this distribution is covered by the same copyright terms |
13 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
14 | * |
15 | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | * the code are not to be removed. |
17 | * If this package is used in a product, Eric Young should be given attribution |
18 | * as the author of the parts of the library used. |
19 | * This can be in the form of a textual message at program startup or |
20 | * in documentation (online or textual) provided with the package. |
21 | * |
22 | * Redistribution and use in source and binary forms, with or without |
23 | * modification, are permitted provided that the following conditions |
24 | * are met: |
25 | * 1. Redistributions of source code must retain the copyright |
26 | * notice, this list of conditions and the following disclaimer. |
27 | * 2. Redistributions in binary form must reproduce the above copyright |
28 | * notice, this list of conditions and the following disclaimer in the |
29 | * documentation and/or other materials provided with the distribution. |
30 | * 3. All advertising materials mentioning features or use of this software |
31 | * must display the following acknowledgement: |
32 | * "This product includes cryptographic software written by |
33 | * Eric Young (eay@cryptsoft.com)" |
34 | * The word 'cryptographic' can be left out if the rouines from the library |
35 | * being used are not cryptographic related :-). |
36 | * 4. If you include any Windows specific code (or a derivative thereof) from |
37 | * the apps directory (application code) you must include an acknowledgement: |
38 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
39 | * |
40 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
44 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
45 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
46 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
48 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
49 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
50 | * SUCH DAMAGE. |
51 | * |
52 | * The licence and distribution terms for any publically available version or |
53 | * derivative of this code cannot be changed. i.e. this code cannot simply be |
54 | * copied and put under another distribution licence |
55 | * [including the GNU Public Licence.] */ |
56 | |
57 | #include <openssl/asn1.h> |
58 | |
59 | #include <string.h> |
60 | #include <time.h> |
61 | |
62 | #include <openssl/asn1t.h> |
63 | #include <openssl/buf.h> |
64 | #include <openssl/err.h> |
65 | #include <openssl/mem.h> |
66 | |
67 | #include "asn1_locl.h" |
68 | |
69 | /* |
70 | * This is an implementation of the ASN1 Time structure which is: Time ::= |
71 | * CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve |
72 | * Henson. |
73 | */ |
74 | |
75 | IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) |
76 | |
77 | IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) |
78 | |
79 | ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) |
80 | { |
81 | return ASN1_TIME_adj(s, t, 0, 0); |
82 | } |
83 | |
84 | ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, |
85 | int offset_day, long offset_sec) |
86 | { |
87 | struct tm *ts; |
88 | struct tm data; |
89 | |
90 | ts = OPENSSL_gmtime(&t, &data); |
91 | if (ts == NULL) { |
92 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME); |
93 | return NULL; |
94 | } |
95 | if (offset_day || offset_sec) { |
96 | if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) |
97 | return NULL; |
98 | } |
99 | if ((ts->tm_year >= 50) && (ts->tm_year < 150)) |
100 | return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); |
101 | return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); |
102 | } |
103 | |
104 | int ASN1_TIME_check(ASN1_TIME *t) |
105 | { |
106 | if (t->type == V_ASN1_GENERALIZEDTIME) |
107 | return ASN1_GENERALIZEDTIME_check(t); |
108 | else if (t->type == V_ASN1_UTCTIME) |
109 | return ASN1_UTCTIME_check(t); |
110 | return 0; |
111 | } |
112 | |
113 | /* Convert an ASN1_TIME structure to GeneralizedTime */ |
114 | ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, |
115 | ASN1_GENERALIZEDTIME **out) |
116 | { |
117 | ASN1_GENERALIZEDTIME *ret = NULL; |
118 | char *str; |
119 | int newlen; |
120 | |
121 | if (!ASN1_TIME_check(t)) |
122 | return NULL; |
123 | |
124 | if (!out || !*out) { |
125 | if (!(ret = ASN1_GENERALIZEDTIME_new())) |
126 | goto err; |
127 | } else { |
128 | ret = *out; |
129 | } |
130 | |
131 | /* If already GeneralizedTime just copy across */ |
132 | if (t->type == V_ASN1_GENERALIZEDTIME) { |
133 | if (!ASN1_STRING_set(ret, t->data, t->length)) |
134 | goto err; |
135 | goto done; |
136 | } |
137 | |
138 | /* grow the string */ |
139 | if (!ASN1_STRING_set(ret, NULL, t->length + 2)) |
140 | goto err; |
141 | /* ASN1_STRING_set() allocated 'len + 1' bytes. */ |
142 | newlen = t->length + 2 + 1; |
143 | str = (char *)ret->data; |
144 | /* Work out the century and prepend */ |
145 | if (t->data[0] >= '5') |
146 | BUF_strlcpy(str, "19" , newlen); |
147 | else |
148 | BUF_strlcpy(str, "20" , newlen); |
149 | |
150 | BUF_strlcat(str, (char *)t->data, newlen); |
151 | |
152 | done: |
153 | if (out != NULL && *out == NULL) |
154 | *out = ret; |
155 | return ret; |
156 | |
157 | err: |
158 | if (out == NULL || *out != ret) |
159 | ASN1_GENERALIZEDTIME_free(ret); |
160 | return NULL; |
161 | } |
162 | |
163 | |
164 | int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) |
165 | { |
166 | ASN1_TIME t; |
167 | |
168 | t.length = strlen(str); |
169 | t.data = (unsigned char *)str; |
170 | t.flags = 0; |
171 | |
172 | t.type = V_ASN1_UTCTIME; |
173 | |
174 | if (!ASN1_TIME_check(&t)) { |
175 | t.type = V_ASN1_GENERALIZEDTIME; |
176 | if (!ASN1_TIME_check(&t)) |
177 | return 0; |
178 | } |
179 | |
180 | if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) |
181 | return 0; |
182 | |
183 | return 1; |
184 | } |
185 | |
186 | static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t) |
187 | { |
188 | if (t == NULL) { |
189 | time_t now_t; |
190 | time(&now_t); |
191 | if (OPENSSL_gmtime(&now_t, tm)) |
192 | return 1; |
193 | return 0; |
194 | } |
195 | |
196 | if (t->type == V_ASN1_UTCTIME) |
197 | return asn1_utctime_to_tm(tm, t); |
198 | else if (t->type == V_ASN1_GENERALIZEDTIME) |
199 | return asn1_generalizedtime_to_tm(tm, t); |
200 | |
201 | return 0; |
202 | } |
203 | |
204 | int ASN1_TIME_diff(int *pday, int *psec, |
205 | const ASN1_TIME *from, const ASN1_TIME *to) |
206 | { |
207 | struct tm tm_from, tm_to; |
208 | if (!asn1_time_to_tm(&tm_from, from)) |
209 | return 0; |
210 | if (!asn1_time_to_tm(&tm_to, to)) |
211 | return 0; |
212 | return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to); |
213 | } |
214 | |