summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/asn1/a_time_tm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/asn1/a_time_tm.c')
-rw-r--r--src/lib/libcrypto/asn1/a_time_tm.c446
1 files changed, 0 insertions, 446 deletions
diff --git a/src/lib/libcrypto/asn1/a_time_tm.c b/src/lib/libcrypto/asn1/a_time_tm.c
deleted file mode 100644
index aa3cb9994c..0000000000
--- a/src/lib/libcrypto/asn1/a_time_tm.c
+++ /dev/null
@@ -1,446 +0,0 @@
1/* $OpenBSD: a_time_tm.c,v 1.9 2015/12/12 21:02:59 beck Exp $ */
2/*
3 * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17#include <ctype.h>
18#include <limits.h>
19#include <stdio.h>
20#include <string.h>
21#include <time.h>
22
23#include <openssl/asn1t.h>
24#include <openssl/err.h>
25
26#include "o_time.h"
27
28#define RFC5280 0
29#define GENTIME_LENGTH 15
30#define UTCTIME_LENGTH 13
31
32int
33asn1_tm_cmp(struct tm *tm1, struct tm *tm2) {
34 if (tm1->tm_year < tm2->tm_year)
35 return (-1);
36 if (tm1->tm_year > tm2->tm_year)
37 return (1);
38 if (tm1->tm_mon < tm2->tm_mon)
39 return (-1);
40 if (tm1->tm_mon > tm2->tm_mon)
41 return (1);
42 if (tm1->tm_mday < tm2->tm_mday)
43 return (-1);
44 if (tm1->tm_mday > tm2->tm_mday)
45 return (1);
46 if (tm1->tm_hour < tm2->tm_hour)
47 return (-1);
48 if (tm1->tm_hour > tm2->tm_hour)
49 return (1);
50 if (tm1->tm_min < tm2->tm_min)
51 return (-1);
52 if (tm1->tm_min > tm2->tm_min)
53 return (1);
54 if (tm1->tm_sec < tm2->tm_sec)
55 return (-1);
56 if (tm1->tm_sec > tm2->tm_sec)
57 return (1);
58 return 0;
59}
60
61/* Format a time as an RFC 5280 format Generalized time */
62char *
63gentime_string_from_tm(struct tm *tm)
64{
65 char *ret = NULL;
66 int year;
67
68 year = tm->tm_year + 1900;
69 if (year < 0 || year > 9999)
70 return (NULL);
71
72 if (asprintf(&ret, "%04u%02u%02u%02u%02u%02uZ", year,
73 tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
74 tm->tm_sec) == -1)
75 ret = NULL;
76
77 return (ret);
78}
79
80/* Format a time as an RFC 5280 format UTC time */
81char *
82utctime_string_from_tm(struct tm *tm)
83{
84 char *ret = NULL;
85
86 if (tm->tm_year >= 150 || tm->tm_year < 50)
87 return (NULL);
88
89 if (asprintf(&ret, "%02u%02u%02u%02u%02u%02uZ",
90 tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday,
91 tm->tm_hour, tm->tm_min, tm->tm_sec) == -1)
92 ret = NULL;
93
94 return (ret);
95}
96
97/* Format a time correctly for an X509 object as per RFC 5280 */
98char *
99rfc5280_string_from_tm(struct tm *tm)
100{
101 char *ret = NULL;
102 int year;
103
104 year = tm->tm_year + 1900;
105 if (year < 1950 || year > 9999)
106 return (NULL);
107
108 if (year < 2050)
109 ret = utctime_string_from_tm(tm);
110 else
111 ret = gentime_string_from_tm(tm);
112
113 return (ret);
114}
115
116/*
117 * Parse an RFC 5280 format ASN.1 time string.
118 *
119 * mode must be:
120 * 0 if we expect to parse a time as specified in RFC 5280 from an X509 object.
121 * V_ASN1_UTCTIME if we wish to parse on RFC5280 format UTC time.
122 * V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time.
123 *
124 * Returns:
125 * -1 if the string was invalid.
126 * V_ASN1_UTCTIME if the string validated as a UTC time string.
127 * V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string.
128 *
129 * Fills in *tm with the corresponding time if tm is non NULL.
130 */
131#define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0'))
132int
133asn1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode)
134{
135 size_t i;
136 int type = 0;
137 struct tm ltm;
138 struct tm *lt;
139 const char *p;
140
141 if (bytes == NULL)
142 return (-1);
143
144 /* Constrain to valid lengths. */
145 if (len != UTCTIME_LENGTH && len != GENTIME_LENGTH)
146 return (-1);
147
148 lt = tm;
149 if (lt == NULL) {
150 memset(&ltm, 0, sizeof(ltm));
151 lt = &ltm;
152 }
153
154 /* Timezone is required and must be GMT (Zulu). */
155 if (bytes[len - 1] != 'Z')
156 return (-1);
157
158 /* Make sure everything else is digits. */
159 for (i = 0; i < len - 1; i++) {
160 if (isdigit((unsigned char)bytes[i]))
161 continue;
162 return (-1);
163 }
164
165 /*
166 * Validate and convert the time
167 */
168 p = bytes;
169 switch (len) {
170 case GENTIME_LENGTH:
171 if (mode == V_ASN1_UTCTIME)
172 return (-1);
173 lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */
174 type = V_ASN1_GENERALIZEDTIME;
175 /* FALLTHROUGH */
176 case UTCTIME_LENGTH:
177 if (type == 0) {
178 if (mode == V_ASN1_GENERALIZEDTIME)
179 return (-1);
180 type = V_ASN1_UTCTIME;
181 }
182 lt->tm_year += ATOI2(p); /* yy */
183 if (type == V_ASN1_UTCTIME) {
184 if (lt->tm_year < 50)
185 lt->tm_year += 100;
186 }
187 lt->tm_mon = ATOI2(p) - 1; /* mm */
188 if (lt->tm_mon < 0 || lt->tm_mon > 11)
189 return (-1);
190 lt->tm_mday = ATOI2(p); /* dd */
191 if (lt->tm_mday < 1 || lt->tm_mday > 31)
192 return (-1);
193 lt->tm_hour = ATOI2(p); /* HH */
194 if (lt->tm_hour < 0 || lt->tm_hour > 23)
195 return (-1);
196 lt->tm_min = ATOI2(p); /* MM */
197 if (lt->tm_min < 0 || lt->tm_min > 59)
198 return (-1);
199 lt->tm_sec = ATOI2(p); /* SS */
200 /* Leap second 60 is not accepted. Reconsider later? */
201 if (lt->tm_sec < 0 || lt->tm_sec > 59)
202 return (-1);
203 break;
204 default:
205 return (-1);
206 }
207
208 return (type);
209}
210
211/*
212 * ASN1_TIME generic functions.
213 */
214
215static int
216ASN1_TIME_set_string_internal(ASN1_TIME *s, const char *str, int mode)
217{
218 int type;
219 char *tmp;
220
221 if ((type = asn1_time_parse(str, strlen(str), NULL, mode)) == -1)
222 return (0);
223 if (mode != 0 && mode != type)
224 return (0);
225
226 if (s == NULL)
227 return (1);
228
229 if ((tmp = strdup(str)) == NULL)
230 return (0);
231 free(s->data);
232 s->data = tmp;
233 s->length = strlen(tmp);
234 s->type = type;
235
236 return (1);
237}
238
239static ASN1_TIME *
240ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
241 int mode)
242{
243 int allocated = 0;
244 struct tm tm;
245 size_t len;
246 char * p;
247
248 if (gmtime_r(&t, &tm) == NULL)
249 return (NULL);
250
251 if (offset_day || offset_sec) {
252 if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec))
253 return (NULL);
254 }
255
256 switch (mode) {
257 case V_ASN1_UTCTIME:
258 p = utctime_string_from_tm(&tm);
259 break;
260 case V_ASN1_GENERALIZEDTIME:
261 p = gentime_string_from_tm(&tm);
262 break;
263 case RFC5280:
264 p = rfc5280_string_from_tm(&tm);
265 break;
266 default:
267 return (NULL);
268 }
269 if (p == NULL) {
270 ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ,
271 ASN1_R_ILLEGAL_TIME_VALUE);
272 return (NULL);
273 }
274
275 if (s == NULL) {
276 if ((s = ASN1_TIME_new()) == NULL)
277 return (NULL);
278 allocated = 1;
279 }
280
281 len = strlen(p);
282 switch (len) {
283 case GENTIME_LENGTH:
284 s->type = V_ASN1_GENERALIZEDTIME;
285 break;
286 case UTCTIME_LENGTH:
287 s->type = V_ASN1_UTCTIME;
288 break;
289 default:
290 if (allocated)
291 ASN1_TIME_free(s);
292 free(p);
293 return (NULL);
294 }
295 free(s->data);
296 s->data = p;
297 s->length = len;
298 return (s);
299}
300
301ASN1_TIME *
302ASN1_TIME_set(ASN1_TIME *s, time_t t)
303{
304 return (ASN1_TIME_adj(s, t, 0, 0));
305}
306
307ASN1_TIME *
308ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec)
309{
310 return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, RFC5280));
311}
312
313int
314ASN1_TIME_check(ASN1_TIME *t)
315{
316 if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
317 return (0);
318 return (t->type == asn1_time_parse(t->data, t->length, NULL, t->type));
319}
320
321ASN1_GENERALIZEDTIME *
322ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
323{
324 ASN1_GENERALIZEDTIME *tmp = NULL;
325 struct tm tm;
326 char *str;
327
328 if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
329 return (NULL);
330
331 memset(&tm, 0, sizeof(tm));
332 if (t->type != asn1_time_parse(t->data, t->length, &tm, t->type))
333 return (NULL);
334 if ((str = gentime_string_from_tm(&tm)) == NULL)
335 return (NULL);
336
337 if (out != NULL)
338 tmp = *out;
339 if (tmp == NULL && (tmp = ASN1_GENERALIZEDTIME_new()) == NULL) {
340 free(str);
341 return (NULL);
342 }
343 if (out != NULL)
344 *out = tmp;
345
346 free(tmp->data);
347 tmp->data = str;
348 tmp->length = strlen(str);
349 return (tmp);
350}
351
352int
353ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
354{
355 return (ASN1_TIME_set_string_internal(s, str, 0));
356}
357
358/*
359 * ASN1_UTCTIME wrappers
360 */
361
362int
363ASN1_UTCTIME_check(ASN1_UTCTIME *d)
364{
365 if (d->type != V_ASN1_UTCTIME)
366 return (0);
367 return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type));
368}
369
370int
371ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
372{
373 if (s != NULL && s->type != V_ASN1_UTCTIME)
374 return (0);
375 return (ASN1_TIME_set_string_internal(s, str, V_ASN1_UTCTIME));
376}
377
378ASN1_UTCTIME *
379ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
380{
381 return (ASN1_UTCTIME_adj(s, t, 0, 0));
382}
383
384ASN1_UTCTIME *
385ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec)
386{
387 return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
388 V_ASN1_UTCTIME));
389}
390
391int
392ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t2)
393{
394 struct tm tm1, tm2;
395
396 /*
397 * This function has never handled failure conditions properly
398 * and should be deprecated. The OpenSSL version used to
399 * simply follow NULL pointers on failure. BoringSSL and
400 * OpenSSL now make it return -2 on failure.
401 *
402 * The danger is that users of this function will not
403 * differentiate the -2 failure case from t1 < t2.
404 */
405 if (asn1_time_parse(s->data, s->length, &tm1, V_ASN1_UTCTIME) == -1)
406 return (-2); /* XXX */
407
408 if (gmtime_r(&t2, &tm2) == NULL)
409 return (-2); /* XXX */
410
411 return asn1_tm_cmp(&tm1, &tm2);
412}
413
414/*
415 * ASN1_GENERALIZEDTIME wrappers
416 */
417
418int
419ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d)
420{
421 if (d->type != V_ASN1_GENERALIZEDTIME)
422 return (0);
423 return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type));
424}
425
426int
427ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
428{
429 if (s != NULL && s->type != V_ASN1_GENERALIZEDTIME)
430 return (0);
431 return (ASN1_TIME_set_string_internal(s, str, V_ASN1_GENERALIZEDTIME));
432}
433
434ASN1_GENERALIZEDTIME *
435ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t)
436{
437 return (ASN1_GENERALIZEDTIME_adj(s, t, 0, 0));
438}
439
440ASN1_GENERALIZEDTIME *
441ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day,
442 long offset_sec)
443{
444 return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
445 V_ASN1_GENERALIZEDTIME));
446}