Refactor ASN1_TIME_print functions
[openssl.git] / crypto / asn1 / a_utctm.c
1 /*
2  * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include <time.h>
12 #include "internal/cryptlib.h"
13 #include <openssl/asn1.h>
14 #include "asn1_locl.h"
15
16 int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
17 {
18     /* wrapper around ans1_time_to_tm */
19     if (d->type != V_ASN1_UTCTIME)
20         return 0;
21     return asn1_time_to_tm(tm, d);
22 }
23
24 int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
25 {
26     return asn1_utctime_to_tm(NULL, d);
27 }
28
29 int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
30 {
31     ASN1_UTCTIME t;
32
33     t.type = V_ASN1_UTCTIME;
34     t.length = strlen(str);
35     t.data = (unsigned char *)str;
36     t.flags = 0;
37
38     if (ASN1_UTCTIME_check(&t)) {
39         if (s != NULL) {
40             if (!ASN1_STRING_set((ASN1_STRING *)s, str, t.length))
41                 return 0;
42             s->type = V_ASN1_UTCTIME;
43         }
44         return 1;
45     }
46     return 0;
47 }
48
49 ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
50 {
51     return ASN1_UTCTIME_adj(s, t, 0, 0);
52 }
53
54 ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
55                                int offset_day, long offset_sec)
56 {
57     char *p;
58     struct tm *ts;
59     struct tm data;
60     const size_t len = 20;
61     int free_s = 0;
62
63     if (s == NULL) {
64         s = ASN1_UTCTIME_new();
65         if (s == NULL)
66             goto err;
67         free_s = 1;
68     }
69
70     ts = OPENSSL_gmtime(&t, &data);
71     if (ts == NULL)
72         goto err;
73
74     if (offset_day || offset_sec) {
75         if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
76             goto err;
77     }
78
79     if ((ts->tm_year < 50) || (ts->tm_year >= 150))
80         goto err;
81
82     p = (char *)s->data;
83     if ((p == NULL) || ((size_t)s->length < len)) {
84         p = OPENSSL_malloc(len);
85         if (p == NULL) {
86             ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE);
87             goto err;
88         }
89         OPENSSL_free(s->data);
90         s->data = (unsigned char *)p;
91     }
92
93     s->length = BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ",
94                              ts->tm_year % 100, ts->tm_mon + 1, ts->tm_mday,
95                              ts->tm_hour, ts->tm_min, ts->tm_sec);
96     s->type = V_ASN1_UTCTIME;
97 #ifdef CHARSET_EBCDIC_not
98     ebcdic2ascii(s->data, s->data, s->length);
99 #endif
100     return s;
101  err:
102     if (free_s)
103         ASN1_UTCTIME_free(s);
104     return NULL;
105 }
106
107 int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
108 {
109     struct tm stm, ttm;
110     int day, sec;
111
112     if (!asn1_utctime_to_tm(&stm, s))
113         return -2;
114
115     if (OPENSSL_gmtime(&t, &ttm) == NULL)
116         return -2;
117
118     if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
119         return -2;
120
121     if (day > 0)
122         return 1;
123     if (day < 0)
124         return -1;
125     if (sec > 0)
126         return 1;
127     if (sec < 0)
128         return -1;
129     return 0;
130 }
131
132 int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
133 {
134     if (tm->type != V_ASN1_UTCTIME)
135         return 0;
136     return ASN1_TIME_print(bp, tm);
137 }