]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/asn1/a_utctm.c
Introduce ASN1_TIME_set_string_X509 API
[thirdparty/openssl.git] / crypto / asn1 / a_utctm.c
1 /*
2 * Copyright 1995-2016 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 static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
19 static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
20 char *a;
21 int n, i, l, o, min_l = 11, strict = 0;
22
23 if (d->type != V_ASN1_UTCTIME)
24 return (0);
25 l = d->length;
26 a = (char *)d->data;
27 o = 0;
28
29 /*
30 * ASN1_STRING_FLAG_X509_TIME is used to enforce RFC 5280
31 * time string format, in which:
32 *
33 * 1. "seconds" is a 'MUST'
34 * 2. "Zulu" timezone is a 'MUST'
35 * 3. "+|-" is not allowed to indicate a time zone
36 */
37
38 if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
39 min_l = 13;
40 strict = 1;
41 }
42
43 if (l < min_l)
44 goto err;
45 for (i = 0; i < 6; i++) {
46 if (!strict && (i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
47 i++;
48 if (tm)
49 tm->tm_sec = 0;
50 break;
51 }
52 if ((a[o] < '0') || (a[o] > '9'))
53 goto err;
54 n = a[o] - '0';
55 /* incomplete 2-digital number */
56 if (++o == l)
57 goto err;
58
59 if ((a[o] < '0') || (a[o] > '9'))
60 goto err;
61 n = (n * 10) + a[o] - '0';
62 /* no more bytes to read, but we haven't seen time-zone yet */
63 if (++o == l)
64 goto err;
65
66 if ((n < min[i]) || (n > max[i]))
67 goto err;
68 if (tm) {
69 switch (i) {
70 case 0:
71 tm->tm_year = n < 50 ? n + 100 : n;
72 break;
73 case 1:
74 tm->tm_mon = n - 1;
75 break;
76 case 2:
77 tm->tm_mday = n;
78 break;
79 case 3:
80 tm->tm_hour = n;
81 break;
82 case 4:
83 tm->tm_min = n;
84 break;
85 case 5:
86 tm->tm_sec = n;
87 break;
88 }
89 }
90 }
91
92 /*
93 * 'o' will never point to '\0' at this point, the only chance
94 * 'o' can point th '\0' is either the subsequent if or the first
95 * else if is true.
96 */
97 if (a[o] == 'Z') {
98 o++;
99 } else if (!strict && ((a[o] == '+') || (a[o] == '-'))) {
100 int offsign = a[o] == '-' ? 1 : -1, offset = 0;
101 o++;
102 if (o + 4 != l)
103 goto err;
104 for (i = 6; i < 8; i++) {
105 if ((a[o] < '0') || (a[o] > '9'))
106 goto err;
107 n = a[o] - '0';
108 o++;
109 if ((a[o] < '0') || (a[o] > '9'))
110 goto err;
111 n = (n * 10) + a[o] - '0';
112 if ((n < min[i]) || (n > max[i]))
113 goto err;
114 if (tm) {
115 if (i == 6)
116 offset = n * 3600;
117 else if (i == 7)
118 offset += n * 60;
119 }
120 o++;
121 }
122 if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
123 return 0;
124 } else {
125 /* not Z, or not +/- in non-strict mode */
126 return 0;
127 }
128 return o == l;
129 err:
130 return 0;
131 }
132
133 int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
134 {
135 return asn1_utctime_to_tm(NULL, d);
136 }
137
138 int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
139 {
140 ASN1_UTCTIME t;
141
142 t.type = V_ASN1_UTCTIME;
143 t.length = strlen(str);
144 t.data = (unsigned char *)str;
145 t.flags = 0;
146
147 if (ASN1_UTCTIME_check(&t)) {
148 if (s != NULL) {
149 if (!ASN1_STRING_set((ASN1_STRING *)s, str, t.length))
150 return 0;
151 s->type = V_ASN1_UTCTIME;
152 }
153 return (1);
154 } else
155 return (0);
156 }
157
158 ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
159 {
160 return ASN1_UTCTIME_adj(s, t, 0, 0);
161 }
162
163 ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
164 int offset_day, long offset_sec)
165 {
166 char *p;
167 struct tm *ts;
168 struct tm data;
169 size_t len = 20;
170 int free_s = 0;
171
172 if (s == NULL) {
173 s = ASN1_UTCTIME_new();
174 if (s == NULL)
175 goto err;
176 free_s = 1;
177 }
178
179 ts = OPENSSL_gmtime(&t, &data);
180 if (ts == NULL)
181 goto err;
182
183 if (offset_day || offset_sec) {
184 if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
185 goto err;
186 }
187
188 if ((ts->tm_year < 50) || (ts->tm_year >= 150))
189 goto err;
190
191 p = (char *)s->data;
192 if ((p == NULL) || ((size_t)s->length < len)) {
193 p = OPENSSL_malloc(len);
194 if (p == NULL) {
195 ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE);
196 goto err;
197 }
198 OPENSSL_free(s->data);
199 s->data = (unsigned char *)p;
200 }
201
202 BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
203 ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
204 ts->tm_sec);
205 s->length = strlen(p);
206 s->type = V_ASN1_UTCTIME;
207 #ifdef CHARSET_EBCDIC_not
208 ebcdic2ascii(s->data, s->data, s->length);
209 #endif
210 return (s);
211 err:
212 if (free_s)
213 ASN1_UTCTIME_free(s);
214 return NULL;
215 }
216
217 int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
218 {
219 struct tm stm, ttm;
220 int day, sec;
221
222 if (!asn1_utctime_to_tm(&stm, s))
223 return -2;
224
225 if (!OPENSSL_gmtime(&t, &ttm))
226 return -2;
227
228 if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
229 return -2;
230
231 if (day > 0)
232 return 1;
233 if (day < 0)
234 return -1;
235 if (sec > 0)
236 return 1;
237 if (sec < 0)
238 return -1;
239 return 0;
240 }
241
242 int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
243 {
244 const char *v;
245 int gmt = 0;
246 int i;
247 int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
248
249 i = tm->length;
250 v = (const char *)tm->data;
251
252 if (i < 10)
253 goto err;
254 if (v[i - 1] == 'Z')
255 gmt = 1;
256 for (i = 0; i < 10; i++)
257 if ((v[i] > '9') || (v[i] < '0'))
258 goto err;
259 y = (v[0] - '0') * 10 + (v[1] - '0');
260 if (y < 50)
261 y += 100;
262 M = (v[2] - '0') * 10 + (v[3] - '0');
263 if ((M > 12) || (M < 1))
264 goto err;
265 d = (v[4] - '0') * 10 + (v[5] - '0');
266 h = (v[6] - '0') * 10 + (v[7] - '0');
267 m = (v[8] - '0') * 10 + (v[9] - '0');
268 if (tm->length >= 12 &&
269 (v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9'))
270 s = (v[10] - '0') * 10 + (v[11] - '0');
271
272 if (BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
273 _asn1_mon[M - 1], d, h, m, s, y + 1900,
274 (gmt) ? " GMT" : "") <= 0)
275 return (0);
276 else
277 return (1);
278 err:
279 BIO_write(bp, "Bad time value", 14);
280 return (0);
281 }