2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
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
12 #include "internal/cryptlib.h"
13 #include <openssl/asn1.h>
14 #include "asn1_locl.h"
16 int asn1_utctime_to_tm(struct tm
*tm
, const ASN1_UTCTIME
*d
)
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 };
21 int n
, i
, l
, o
, min_l
= 11, strict
= 0;
23 if (d
->type
!= V_ASN1_UTCTIME
)
30 * ASN1_STRING_FLAG_X509_TIME is used to enforce RFC 5280
31 * time string format, in which:
33 * 1. "seconds" is a 'MUST'
34 * 2. "Zulu" timezone is a 'MUST'
35 * 3. "+|-" is not allowed to indicate a time zone
38 if (d
->flags
& ASN1_STRING_FLAG_X509_TIME
) {
45 for (i
= 0; i
< 6; i
++) {
46 if (!strict
&& (i
== 5) && ((a
[o
] == 'Z') || (a
[o
] == '+') || (a
[o
] == '-'))) {
52 if ((a
[o
] < '0') || (a
[o
] > '9'))
55 /* incomplete 2-digital number */
59 if ((a
[o
] < '0') || (a
[o
] > '9'))
61 n
= (n
* 10) + a
[o
] - '0';
62 /* no more bytes to read, but we haven't seen time-zone yet */
66 if ((n
< min
[i
]) || (n
> max
[i
]))
71 tm
->tm_year
= n
< 50 ? n
+ 100 : n
;
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
99 } else if (!strict
&& ((a
[o
] == '+') || (a
[o
] == '-'))) {
100 int offsign
= a
[o
] == '-' ? 1 : -1, offset
= 0;
104 for (i
= 6; i
< 8; i
++) {
105 if ((a
[o
] < '0') || (a
[o
] > '9'))
109 if ((a
[o
] < '0') || (a
[o
] > '9'))
111 n
= (n
* 10) + a
[o
] - '0';
112 if ((n
< min
[i
]) || (n
> max
[i
]))
122 if (offset
&& !OPENSSL_gmtime_adj(tm
, 0, offset
* offsign
))
125 /* not Z, or not +/- in non-strict mode */
133 int ASN1_UTCTIME_check(const ASN1_UTCTIME
*d
)
135 return asn1_utctime_to_tm(NULL
, d
);
138 int ASN1_UTCTIME_set_string(ASN1_UTCTIME
*s
, const char *str
)
142 t
.type
= V_ASN1_UTCTIME
;
143 t
.length
= strlen(str
);
144 t
.data
= (unsigned char *)str
;
147 if (ASN1_UTCTIME_check(&t
)) {
149 if (!ASN1_STRING_set((ASN1_STRING
*)s
, str
, t
.length
))
151 s
->type
= V_ASN1_UTCTIME
;
158 ASN1_UTCTIME
*ASN1_UTCTIME_set(ASN1_UTCTIME
*s
, time_t t
)
160 return ASN1_UTCTIME_adj(s
, t
, 0, 0);
163 ASN1_UTCTIME
*ASN1_UTCTIME_adj(ASN1_UTCTIME
*s
, time_t t
,
164 int offset_day
, long offset_sec
)
173 s
= ASN1_UTCTIME_new();
179 ts
= OPENSSL_gmtime(&t
, &data
);
183 if (offset_day
|| offset_sec
) {
184 if (!OPENSSL_gmtime_adj(ts
, offset_day
, offset_sec
))
188 if ((ts
->tm_year
< 50) || (ts
->tm_year
>= 150))
192 if ((p
== NULL
) || ((size_t)s
->length
< len
)) {
193 p
= OPENSSL_malloc(len
);
195 ASN1err(ASN1_F_ASN1_UTCTIME_ADJ
, ERR_R_MALLOC_FAILURE
);
198 OPENSSL_free(s
->data
);
199 s
->data
= (unsigned char *)p
;
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
,
205 s
->length
= strlen(p
);
206 s
->type
= V_ASN1_UTCTIME
;
207 #ifdef CHARSET_EBCDIC_not
208 ebcdic2ascii(s
->data
, s
->data
, s
->length
);
213 ASN1_UTCTIME_free(s
);
217 int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME
*s
, time_t t
)
222 if (!asn1_utctime_to_tm(&stm
, s
))
225 if (!OPENSSL_gmtime(&t
, &ttm
))
228 if (!OPENSSL_gmtime_diff(&day
, &sec
, &ttm
, &stm
))
242 int ASN1_UTCTIME_print(BIO
*bp
, const ASN1_UTCTIME
*tm
)
247 int y
= 0, M
= 0, d
= 0, h
= 0, m
= 0, s
= 0;
250 v
= (const char *)tm
->data
;
256 for (i
= 0; i
< 10; i
++)
257 if ((v
[i
] > '9') || (v
[i
] < '0'))
259 y
= (v
[0] - '0') * 10 + (v
[1] - '0');
262 M
= (v
[2] - '0') * 10 + (v
[3] - '0');
263 if ((M
> 12) || (M
< 1))
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');
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)
279 BIO_write(bp
, "Bad time value", 14);