diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/asn1/a_gentm.c | 106 | ||||
-rw-r--r-- | src/lib/libcrypto/asn1/a_time.c | 25 | ||||
-rw-r--r-- | src/lib/libcrypto/asn1/a_time_tm.c | 257 | ||||
-rw-r--r-- | src/lib/libcrypto/asn1/a_utctm.c | 80 | ||||
-rw-r--r-- | src/lib/libcrypto/asn1/asn1_locl.h | 6 | ||||
-rw-r--r-- | src/lib/libcrypto/crypto/Makefile | 3 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_lcl.h | 1 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 128 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/asn1/a_gentm.c | 106 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/asn1/a_time.c | 25 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/asn1/a_time_tm.c | 257 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/asn1/a_utctm.c | 80 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/asn1/asn1_locl.h | 6 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/x509/x509_lcl.h | 1 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/x509/x509_vfy.c | 128 |
15 files changed, 666 insertions, 543 deletions
diff --git a/src/lib/libcrypto/asn1/a_gentm.c b/src/lib/libcrypto/asn1/a_gentm.c index 4cee40437c..594eb63058 100644 --- a/src/lib/libcrypto/asn1/a_gentm.c +++ b/src/lib/libcrypto/asn1/a_gentm.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: a_gentm.c,v 1.24 2015/09/30 18:04:02 jsing Exp $ */ | 1 | /* $OpenBSD: a_gentm.c,v 1.25 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -66,86 +66,14 @@ | |||
66 | #include <openssl/err.h> | 66 | #include <openssl/err.h> |
67 | 67 | ||
68 | #include "o_time.h" | 68 | #include "o_time.h" |
69 | #include "asn1_locl.h" | ||
69 | 70 | ||
70 | int | 71 | int |
71 | ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d) | 72 | ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d) |
72 | { | 73 | { |
73 | static const int min[9] = {0, 0, 1, 1, 0, 0, 0, 0, 0}; | ||
74 | static const int max[9] = {99, 99, 12, 31, 23, 59, 59, 12, 59}; | ||
75 | char *a; | ||
76 | int n, i, l, o; | ||
77 | |||
78 | if (d->type != V_ASN1_GENERALIZEDTIME) | 74 | if (d->type != V_ASN1_GENERALIZEDTIME) |
79 | return (0); | 75 | return (0); |
80 | l = d->length; | 76 | return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); |
81 | a = (char *)d->data; | ||
82 | o = 0; | ||
83 | /* GENERALIZEDTIME is similar to UTCTIME except the year is | ||
84 | * represented as YYYY. This stuff treats everything as a two digit | ||
85 | * field so make first two fields 00 to 99 | ||
86 | */ | ||
87 | if (l < 13) | ||
88 | goto err; | ||
89 | for (i = 0; i < 7; i++) { | ||
90 | if ((i == 6) && ((a[o] == 'Z') || | ||
91 | (a[o] == '+') || (a[o] == '-'))) { | ||
92 | i++; | ||
93 | break; | ||
94 | } | ||
95 | if ((a[o] < '0') || (a[o] > '9')) | ||
96 | goto err; | ||
97 | n= a[o]-'0'; | ||
98 | if (++o > l) | ||
99 | goto err; | ||
100 | |||
101 | if ((a[o] < '0') || (a[o] > '9')) | ||
102 | goto err; | ||
103 | n = (n * 10)+ a[o] - '0'; | ||
104 | if (++o > l) | ||
105 | goto err; | ||
106 | |||
107 | if ((n < min[i]) || (n > max[i])) | ||
108 | goto err; | ||
109 | } | ||
110 | /* Optional fractional seconds: decimal point followed by one | ||
111 | * or more digits. | ||
112 | */ | ||
113 | if (a[o] == '.') { | ||
114 | if (++o > l) | ||
115 | goto err; | ||
116 | i = o; | ||
117 | while ((a[o] >= '0') && (a[o] <= '9') && (o <= l)) | ||
118 | o++; | ||
119 | /* Must have at least one digit after decimal point */ | ||
120 | if (i == o) | ||
121 | goto err; | ||
122 | } | ||
123 | |||
124 | if (a[o] == 'Z') | ||
125 | o++; | ||
126 | else if ((a[o] == '+') || (a[o] == '-')) { | ||
127 | o++; | ||
128 | if (o + 4 > l) | ||
129 | goto err; | ||
130 | for (i = 7; i < 9; i++) { | ||
131 | if ((a[o] < '0') || (a[o] > '9')) | ||
132 | goto err; | ||
133 | n = a[o] - '0'; | ||
134 | o++; | ||
135 | if ((a[o] < '0') || (a[o] > '9')) | ||
136 | goto err; | ||
137 | n = (n * 10) + a[o] - '0'; | ||
138 | if ((n < min[i]) || (n > max[i])) | ||
139 | goto err; | ||
140 | o++; | ||
141 | } | ||
142 | } else { | ||
143 | /* Missing time zone information. */ | ||
144 | goto err; | ||
145 | } | ||
146 | return (o == l); | ||
147 | err: | ||
148 | return (0); | ||
149 | } | 77 | } |
150 | 78 | ||
151 | int | 79 | int |
@@ -179,34 +107,26 @@ ASN1_GENERALIZEDTIME_adj_internal(ASN1_GENERALIZEDTIME *s, time_t t, | |||
179 | int offset_day, long offset_sec) | 107 | int offset_day, long offset_sec) |
180 | { | 108 | { |
181 | char *p; | 109 | char *p; |
182 | struct tm *ts; | 110 | struct tm *tm; |
183 | struct tm data; | 111 | struct tm data; |
184 | size_t len = 20; | ||
185 | 112 | ||
186 | ts = gmtime_r(&t, &data); | 113 | tm = gmtime_r(&t, &data); |
187 | if (ts == NULL) | 114 | if (tm == NULL) |
188 | return (NULL); | 115 | return (NULL); |
189 | 116 | ||
190 | if (offset_day || offset_sec) { | 117 | if (offset_day || offset_sec) { |
191 | if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) | 118 | if (!OPENSSL_gmtime_adj(tm, offset_day, offset_sec)) |
192 | return NULL; | 119 | return NULL; |
193 | } | 120 | } |
194 | 121 | ||
195 | p = (char *)s->data; | 122 | if ((p = gentime_string_from_tm(tm)) == NULL) { |
196 | if ((p == NULL) || ((size_t)s->length < len)) { | 123 | ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, ERR_R_MALLOC_FAILURE); |
197 | p = malloc(len); | 124 | return (NULL); |
198 | if (p == NULL) { | ||
199 | ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, | ||
200 | ERR_R_MALLOC_FAILURE); | ||
201 | return (NULL); | ||
202 | } | ||
203 | free(s->data); | ||
204 | s->data = (unsigned char *)p; | ||
205 | } | 125 | } |
206 | 126 | free(s->data); | |
207 | snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900, | 127 | s->data = p; |
208 | ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec); | ||
209 | s->length = strlen(p); | 128 | s->length = strlen(p); |
129 | |||
210 | s->type = V_ASN1_GENERALIZEDTIME; | 130 | s->type = V_ASN1_GENERALIZEDTIME; |
211 | return (s); | 131 | return (s); |
212 | } | 132 | } |
diff --git a/src/lib/libcrypto/asn1/a_time.c b/src/lib/libcrypto/asn1/a_time.c index 25a1805640..a6c7c8e736 100644 --- a/src/lib/libcrypto/asn1/a_time.c +++ b/src/lib/libcrypto/asn1/a_time.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: a_time.c,v 1.25 2015/09/30 18:04:02 jsing Exp $ */ | 1 | /* $OpenBSD: a_time.c,v 1.26 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* ==================================================================== | 2 | /* ==================================================================== |
3 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. | 3 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. |
4 | * | 4 | * |
@@ -68,7 +68,7 @@ | |||
68 | #include <openssl/err.h> | 68 | #include <openssl/err.h> |
69 | 69 | ||
70 | #include "o_time.h" | 70 | #include "o_time.h" |
71 | 71 | #include "asn1_locl.h" | |
72 | 72 | ||
73 | const ASN1_ITEM ASN1_TIME_it = { | 73 | const ASN1_ITEM ASN1_TIME_it = { |
74 | .itype = ASN1_ITYPE_MSTRING, | 74 | .itype = ASN1_ITYPE_MSTRING, |
@@ -135,11 +135,9 @@ ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec) | |||
135 | int | 135 | int |
136 | ASN1_TIME_check(ASN1_TIME *t) | 136 | ASN1_TIME_check(ASN1_TIME *t) |
137 | { | 137 | { |
138 | if (t->type == V_ASN1_GENERALIZEDTIME) | 138 | if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME) |
139 | return ASN1_GENERALIZEDTIME_check(t); | 139 | return 0; |
140 | else if (t->type == V_ASN1_UTCTIME) | 140 | return (t->type == asn1_time_parse(t->data, t->length, NULL, t->type)); |
141 | return ASN1_UTCTIME_check(t); | ||
142 | return 0; | ||
143 | } | 141 | } |
144 | 142 | ||
145 | /* Convert an ASN1_TIME structure to GeneralizedTime */ | 143 | /* Convert an ASN1_TIME structure to GeneralizedTime */ |
@@ -210,13 +208,12 @@ ASN1_TIME_set_string(ASN1_TIME *s, const char *str) | |||
210 | t.data = (unsigned char *)str; | 208 | t.data = (unsigned char *)str; |
211 | t.flags = 0; | 209 | t.flags = 0; |
212 | 210 | ||
213 | t.type = V_ASN1_UTCTIME; | 211 | t.type = asn1_time_parse(t.data, t.length, NULL, V_ASN1_UTCTIME); |
214 | 212 | if (t.type == -1) | |
215 | if (!ASN1_TIME_check(&t)) { | 213 | t.type = asn1_time_parse(t.data, t.length, NULL, |
216 | t.type = V_ASN1_GENERALIZEDTIME; | 214 | V_ASN1_GENERALIZEDTIME); |
217 | if (!ASN1_TIME_check(&t)) | 215 | if (t.type == -1) |
218 | return 0; | 216 | return 0; |
219 | } | ||
220 | 217 | ||
221 | if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) | 218 | if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) |
222 | return 0; | 219 | return 0; |
diff --git a/src/lib/libcrypto/asn1/a_time_tm.c b/src/lib/libcrypto/asn1/a_time_tm.c new file mode 100644 index 0000000000..65f75c68cc --- /dev/null +++ b/src/lib/libcrypto/asn1/a_time_tm.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* $OpenBSD: a_time_tm.c,v 1.1 2015/10/02 15:04:45 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 | |||
18 | #include <stdio.h> | ||
19 | #include <string.h> | ||
20 | #include <time.h> | ||
21 | #include <ctype.h> | ||
22 | #include <sys/limits.h> | ||
23 | |||
24 | #include <openssl/asn1t.h> | ||
25 | #include <openssl/err.h> | ||
26 | |||
27 | #include "o_time.h" | ||
28 | #include "asn1_locl.h" | ||
29 | |||
30 | char * | ||
31 | gentime_string_from_tm(struct tm *tm) | ||
32 | { | ||
33 | char *ret = NULL; | ||
34 | int year; | ||
35 | year = tm->tm_year + 1900; | ||
36 | if (year < 0 || year > 9999) | ||
37 | return (NULL); | ||
38 | if (asprintf(&ret, "%04u%02u%02u%02u%02u%02uZ", year, | ||
39 | tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
40 | tm->tm_sec) == -1) | ||
41 | ret = NULL; | ||
42 | return (ret); | ||
43 | } | ||
44 | |||
45 | char * | ||
46 | utctime_string_from_tm(struct tm *tm) | ||
47 | { | ||
48 | char *ret = NULL; | ||
49 | if (tm->tm_year >= 150 || tm->tm_year < 50) | ||
50 | return (NULL); | ||
51 | if (asprintf(&ret, "%02u%02u%02u%02u%02u%02uZ", | ||
52 | tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, | ||
53 | tm->tm_hour, tm->tm_min, tm->tm_sec) == -1) | ||
54 | ret = NULL; | ||
55 | return (ret); | ||
56 | } | ||
57 | |||
58 | /* | ||
59 | * Parse an ASN.1 time string. | ||
60 | * | ||
61 | * mode must be: | ||
62 | * 0 if we expect to parse a time as specified in RFC 5280 from an | ||
63 | * X509 certificate. | ||
64 | * V_ASN1_UTCTIME if we wish to parse a legacy ASN1 UTC time. | ||
65 | * V_ASN1_GENERALIZEDTIME if we wish to parse a legacy ASN1 | ||
66 | * Generalizd time. | ||
67 | * | ||
68 | * Returns: | ||
69 | * -1 if the string was invalid. | ||
70 | * V_ASN1_UTCTIME if the string validated as a UTC time string. | ||
71 | * V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string. | ||
72 | * | ||
73 | * Fills in *tm with the corresponding time if tm is non NULL. | ||
74 | */ | ||
75 | #define RFC5280 0 | ||
76 | #define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0')) | ||
77 | int asn1_time_parse(const char * bytes, size_t len, struct tm *tm, int mode) | ||
78 | { | ||
79 | char *p, *buf = NULL, *dot = NULL, *tz = NULL; | ||
80 | int i, offset, noseconds = 0, type = 0; | ||
81 | struct tm ltm; | ||
82 | struct tm *lt; | ||
83 | size_t tlen; | ||
84 | char tzc; | ||
85 | |||
86 | if (bytes == NULL) | ||
87 | goto err; | ||
88 | |||
89 | if (len > INT_MAX) | ||
90 | goto err; | ||
91 | |||
92 | /* Constrain the RFC5280 case within max/min valid lengths. */ | ||
93 | if (mode == RFC5280 && (len > 15 || len < 13)) | ||
94 | goto err; | ||
95 | |||
96 | if ((buf = strndup(bytes, len)) == NULL) | ||
97 | goto err; | ||
98 | lt = tm; | ||
99 | if (lt == NULL) { | ||
100 | time_t t = time(NULL); | ||
101 | lt = gmtime_r(&t, <m); | ||
102 | if (lt == NULL) | ||
103 | goto err; | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * Find position of the optional fractional seconds, and the | ||
108 | * start of the timezone, while ensuring everything else is | ||
109 | * digits. | ||
110 | */ | ||
111 | for (i = 0; i < len; i++) { | ||
112 | char *t = buf + i; | ||
113 | if (isdigit((unsigned char)*t)) | ||
114 | continue; | ||
115 | if (*t == '.' && dot == NULL) { | ||
116 | dot = t; | ||
117 | continue; | ||
118 | } | ||
119 | if ((*t == 'Z' || *t == '+' || *t == '-') && tz == NULL) { | ||
120 | tz = t; | ||
121 | continue; | ||
122 | } | ||
123 | goto err; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Timezone is required. For the non-RFC case it may be | ||
128 | * either Z or +- HHMM, but for RFC5280 it may be only Z. | ||
129 | */ | ||
130 | if (tz == NULL) | ||
131 | goto err; | ||
132 | tzc = *tz; | ||
133 | *tz++ = '\0'; | ||
134 | if (tzc == 'Z') { | ||
135 | if (*tz != '\0') | ||
136 | goto err; | ||
137 | offset = 0; | ||
138 | } else if (mode != RFC5280 && (tzc == '+' || tzc == '-') && | ||
139 | (strlen(tz) == 4)) { | ||
140 | int hours, mins; | ||
141 | hours = ATOI2(tz); | ||
142 | mins = ATOI2(tz); | ||
143 | if (hours > 12 || mins > 59) | ||
144 | goto err; | ||
145 | offset = hours * 3600 + mins * 60; | ||
146 | if (tzc == '-') | ||
147 | offset = -offset; | ||
148 | } else | ||
149 | goto err; | ||
150 | |||
151 | if (mode != RFC5280) { | ||
152 | /* XXX - yuck - OPENSSL_gmtime_adj should go away */ | ||
153 | if (!OPENSSL_gmtime_adj(lt, 0, offset)) | ||
154 | goto err; | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * We only allow fractional seconds to be present if we are in | ||
159 | * the non-RFC case of a Generalized time. RFC 5280 forbids | ||
160 | * fractional seconds. | ||
161 | */ | ||
162 | if (dot != NULL) { | ||
163 | if (mode != V_ASN1_GENERALIZEDTIME) | ||
164 | goto err; | ||
165 | *dot++ = '\0'; | ||
166 | if (!isdigit((unsigned char)*dot)) | ||
167 | goto err; | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Validate and convert the time | ||
172 | */ | ||
173 | p = buf; | ||
174 | tlen = strlen(buf); | ||
175 | switch (tlen) { | ||
176 | case 14: | ||
177 | lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ | ||
178 | if (mode == RFC5280 || mode == V_ASN1_GENERALIZEDTIME) | ||
179 | type = V_ASN1_GENERALIZEDTIME; | ||
180 | else | ||
181 | goto err; | ||
182 | /* FALLTHROUGH */ | ||
183 | case 12: | ||
184 | if (type == 0 && mode == V_ASN1_GENERALIZEDTIME) { | ||
185 | /* | ||
186 | * In the non-RFC case of a Generalized time | ||
187 | * seconds may not have been provided. RFC | ||
188 | * 5280 mandates that seconds must be present. | ||
189 | */ | ||
190 | noseconds = 1; | ||
191 | lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ | ||
192 | type = V_ASN1_GENERALIZEDTIME; | ||
193 | } | ||
194 | /* FALLTHROUGH */ | ||
195 | case 10: | ||
196 | if (type == 0) { | ||
197 | /* | ||
198 | * At this point we must have a UTC time. | ||
199 | * In the RFC 5280 case it must have the | ||
200 | * seconds present. In the non-RFC case | ||
201 | * may have no seconds. | ||
202 | */ | ||
203 | if (mode == V_ASN1_GENERALIZEDTIME) | ||
204 | goto err; | ||
205 | if (tlen == 10) { | ||
206 | if (mode == V_ASN1_UTCTIME) | ||
207 | noseconds = 1; | ||
208 | else | ||
209 | goto err; | ||
210 | } | ||
211 | type = V_ASN1_UTCTIME; | ||
212 | } | ||
213 | lt->tm_year += ATOI2(p); /* yy */ | ||
214 | if (type == V_ASN1_UTCTIME) { | ||
215 | if (lt->tm_year < 50) | ||
216 | lt->tm_year += 100; | ||
217 | } | ||
218 | lt->tm_mon = ATOI2(p); /* mm */ | ||
219 | if ((lt->tm_mon > 12) || !lt->tm_mon) | ||
220 | goto err; | ||
221 | --lt->tm_mon; /* struct tm is 0 - 11 */ | ||
222 | lt->tm_mday = ATOI2(p); /* dd */ | ||
223 | if ((lt->tm_mday > 31) || !lt->tm_mday) | ||
224 | goto err; | ||
225 | lt->tm_hour = ATOI2(p); /* HH */ | ||
226 | if (lt->tm_hour > 23) | ||
227 | goto err; | ||
228 | lt->tm_min = ATOI2(p); /* MM */ | ||
229 | if (lt->tm_min > 59) | ||
230 | goto err; | ||
231 | lt->tm_sec = 0; /* SS */ | ||
232 | if (noseconds) | ||
233 | break; | ||
234 | lt->tm_sec = ATOI2(p); | ||
235 | /* Leap second 60 is not accepted. Reconsider later? */ | ||
236 | if (lt->tm_sec > 59) | ||
237 | goto err; | ||
238 | break; | ||
239 | default: | ||
240 | goto err; | ||
241 | } | ||
242 | |||
243 | /* RFC 5280 section 4.1.2.5 */ | ||
244 | if (mode == RFC5280 && lt->tm_year < 150 && | ||
245 | type != V_ASN1_UTCTIME) | ||
246 | goto err; | ||
247 | if (mode == RFC5280 && lt->tm_year >= 150 && | ||
248 | type != V_ASN1_GENERALIZEDTIME) | ||
249 | goto err; | ||
250 | |||
251 | free(buf); | ||
252 | return type; | ||
253 | |||
254 | err: | ||
255 | free(buf); | ||
256 | return -1; | ||
257 | } | ||
diff --git a/src/lib/libcrypto/asn1/a_utctm.c b/src/lib/libcrypto/asn1/a_utctm.c index ca19a8c7a0..c208d494c3 100644 --- a/src/lib/libcrypto/asn1/a_utctm.c +++ b/src/lib/libcrypto/asn1/a_utctm.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: a_utctm.c,v 1.28 2015/09/30 18:26:07 jsing Exp $ */ | 1 | /* $OpenBSD: a_utctm.c,v 1.29 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -64,66 +64,14 @@ | |||
64 | #include <openssl/err.h> | 64 | #include <openssl/err.h> |
65 | 65 | ||
66 | #include "o_time.h" | 66 | #include "o_time.h" |
67 | #include "asn1_locl.h" | ||
67 | 68 | ||
68 | int | 69 | int |
69 | ASN1_UTCTIME_check(ASN1_UTCTIME *d) | 70 | ASN1_UTCTIME_check(ASN1_UTCTIME *d) |
70 | { | 71 | { |
71 | static const int min[8] = {0, 1, 1, 0, 0, 0, 0, 0}; | ||
72 | static const int max[8] = {99, 12, 31, 23, 59, 59, 12, 59}; | ||
73 | char *a; | ||
74 | int n, i, l, o; | ||
75 | |||
76 | if (d->type != V_ASN1_UTCTIME) | 72 | if (d->type != V_ASN1_UTCTIME) |
77 | return (0); | 73 | return (0); |
78 | l = d->length; | 74 | return(d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); |
79 | a = (char *)d->data; | ||
80 | o = 0; | ||
81 | |||
82 | if (l < 11) | ||
83 | |||
84 | goto err; | ||
85 | for (i = 0; i < 6; i++) { | ||
86 | if ((i == 5) && ((a[o] == 'Z') || | ||
87 | (a[o] == '+') || (a[o] == '-'))) { | ||
88 | i++; | ||
89 | break; | ||
90 | } | ||
91 | if ((a[o] < '0') || (a[o] > '9')) | ||
92 | goto err; | ||
93 | n = a[o]-'0'; | ||
94 | if (++o > l) | ||
95 | goto err; | ||
96 | if ((a[o] < '0') || (a[o] > '9')) | ||
97 | goto err; | ||
98 | n = (n * 10) + a[o] - '0'; | ||
99 | if (++o > l) | ||
100 | goto err; | ||
101 | if ((n < min[i]) || (n > max[i])) | ||
102 | goto err; | ||
103 | } | ||
104 | if (a[o] == 'Z') | ||
105 | o++; | ||
106 | else if ((a[o] == '+') || (a[o] == '-')) { | ||
107 | o++; | ||
108 | if (o + 4 > l) | ||
109 | goto err; | ||
110 | for (i = 6; i < 8; i++) { | ||
111 | if ((a[o] < '0') || (a[o] > '9')) | ||
112 | goto err; | ||
113 | n = a[o] -'0'; | ||
114 | o++; | ||
115 | if ((a[o] < '0') || (a[o] > '9')) | ||
116 | goto err; | ||
117 | n = (n * 10) + a[o] - '0'; | ||
118 | if ((n < min[i]) || (n > max[i])) | ||
119 | goto err; | ||
120 | o++; | ||
121 | } | ||
122 | } | ||
123 | return (o == l); | ||
124 | |||
125 | err: | ||
126 | return (0); | ||
127 | } | 75 | } |
128 | 76 | ||
129 | int | 77 | int |
@@ -159,7 +107,6 @@ ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day, | |||
159 | char *p; | 107 | char *p; |
160 | struct tm *ts; | 108 | struct tm *ts; |
161 | struct tm data; | 109 | struct tm data; |
162 | size_t len = 20; | ||
163 | 110 | ||
164 | ts = gmtime_r(&t, &data); | 111 | ts = gmtime_r(&t, &data); |
165 | if (ts == NULL) | 112 | if (ts == NULL) |
@@ -170,23 +117,14 @@ ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day, | |||
170 | return NULL; | 117 | return NULL; |
171 | } | 118 | } |
172 | 119 | ||
173 | if ((ts->tm_year < 50) || (ts->tm_year >= 150)) | 120 | if ((p = utctime_string_from_tm(ts)) == NULL) { |
174 | return NULL; | 121 | ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE); |
175 | 122 | return (NULL); | |
176 | p = (char *)s->data; | ||
177 | if ((p == NULL) || ((size_t)s->length < len)) { | ||
178 | p = malloc(len); | ||
179 | if (p == NULL) { | ||
180 | ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE); | ||
181 | return (NULL); | ||
182 | } | ||
183 | free(s->data); | ||
184 | s->data = (unsigned char *)p; | ||
185 | } | 123 | } |
186 | 124 | free(s->data); | |
187 | snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100, | 125 | s->data = p; |
188 | ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec); | ||
189 | s->length = strlen(p); | 126 | s->length = strlen(p); |
127 | |||
190 | s->type = V_ASN1_UTCTIME; | 128 | s->type = V_ASN1_UTCTIME; |
191 | return (s); | 129 | return (s); |
192 | } | 130 | } |
diff --git a/src/lib/libcrypto/asn1/asn1_locl.h b/src/lib/libcrypto/asn1/asn1_locl.h index c6c80aa6aa..d4994c7cee 100644 --- a/src/lib/libcrypto/asn1/asn1_locl.h +++ b/src/lib/libcrypto/asn1/asn1_locl.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: asn1_locl.h,v 1.5 2014/06/12 15:49:27 deraadt Exp $ */ | 1 | /* $OpenBSD: asn1_locl.h,v 1.6 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 2006. | 3 | * project 2006. |
4 | */ | 4 | */ |
@@ -58,6 +58,10 @@ | |||
58 | 58 | ||
59 | /* Internal ASN1 structures and functions: not for application use */ | 59 | /* Internal ASN1 structures and functions: not for application use */ |
60 | 60 | ||
61 | char * gentime_string_from_tm(struct tm *tm); | ||
62 | char * utctime_string_from_tm(struct tm *tm); | ||
63 | int asn1_time_parse(const char *, size_t, struct tm *, int); | ||
64 | |||
61 | /* ASN1 print context structure */ | 65 | /* ASN1 print context structure */ |
62 | 66 | ||
63 | struct asn1_pctx_st { | 67 | struct asn1_pctx_st { |
diff --git a/src/lib/libcrypto/crypto/Makefile b/src/lib/libcrypto/crypto/Makefile index 9a58b30627..64ee774518 100644 --- a/src/lib/libcrypto/crypto/Makefile +++ b/src/lib/libcrypto/crypto/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: Makefile,v 1.65 2015/09/14 01:45:03 doug Exp $ | 1 | # $OpenBSD: Makefile,v 1.66 2015/10/02 15:04:45 beck Exp $ |
2 | 2 | ||
3 | LIB= crypto | 3 | LIB= crypto |
4 | 4 | ||
@@ -49,6 +49,7 @@ SRCS+= f_enum.c x_pkey.c a_bool.c x_exten.c bio_asn1.c bio_ndef.c asn_mime.c | |||
49 | SRCS+= asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_bytes.c a_strnid.c | 49 | SRCS+= asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_bytes.c a_strnid.c |
50 | SRCS+= evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c asn_moid.c | 50 | SRCS+= evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c asn_moid.c |
51 | SRCS+= a_set.c | 51 | SRCS+= a_set.c |
52 | SRCS+= a_time_tm.c | ||
52 | 53 | ||
53 | # bf/ | 54 | # bf/ |
54 | SRCS+= bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c | 55 | SRCS+= bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c |
diff --git a/src/lib/libcrypto/x509/x509_lcl.h b/src/lib/libcrypto/x509/x509_lcl.h index b16df78ad7..0c1c130d5c 100644 --- a/src/lib/libcrypto/x509/x509_lcl.h +++ b/src/lib/libcrypto/x509/x509_lcl.h | |||
@@ -57,3 +57,4 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); | 59 | int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); |
60 | int asn1_time_parse(const char *, size_t, struct tm *, int); | ||
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index 8d4d15668e..c48143f351 100644 --- a/src/lib/libcrypto/x509/x509_vfy.c +++ b/src/lib/libcrypto/x509/x509_vfy.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_vfy.c,v 1.45 2015/09/14 16:13:39 jsing Exp $ */ | 1 | /* $OpenBSD: x509_vfy.c,v 1.46 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -1631,106 +1631,50 @@ X509_cmp_current_time(const ASN1_TIME *ctm) | |||
1631 | return X509_cmp_time(ctm, NULL); | 1631 | return X509_cmp_time(ctm, NULL); |
1632 | } | 1632 | } |
1633 | 1633 | ||
1634 | /* | ||
1635 | * Compare a possibly unvalidated ASN1_TIME string against a time_t | ||
1636 | * using RFC 5280 rules for the time string. If *cmp_time is NULL | ||
1637 | * the current system time is used. | ||
1638 | * | ||
1639 | * XXX NOTE that unlike what you expect a "cmp" function to do in C, | ||
1640 | * XXX this one is "special", and returns 0 for error. | ||
1641 | * | ||
1642 | * Returns: | ||
1643 | * -1 if the ASN1_time is earlier than OR the same as *cmp_time. | ||
1644 | * 1 if the ASN1_time is later than *cmp_time. | ||
1645 | * 0 on error. | ||
1646 | */ | ||
1634 | int | 1647 | int |
1635 | X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) | 1648 | X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) |
1636 | { | 1649 | { |
1637 | char *str; | 1650 | time_t time1, time2; |
1638 | ASN1_TIME atm; | 1651 | struct tm tm1; |
1639 | long offset; | 1652 | int ret = 0; |
1640 | char buff1[24], buff2[24], *p; | ||
1641 | int i, j; | ||
1642 | 1653 | ||
1643 | p = buff1; | 1654 | if (cmp_time == NULL) |
1644 | i = ctm->length; | 1655 | time2 = time(NULL); |
1645 | str = (char *)ctm->data; | 1656 | else |
1646 | if (ctm->type == V_ASN1_UTCTIME) { | 1657 | time2 = *cmp_time; |
1647 | if ((i < 11) || (i > 17)) | ||
1648 | return 0; | ||
1649 | memcpy(p, str, 10); | ||
1650 | p += 10; | ||
1651 | str += 10; | ||
1652 | i -= 10; | ||
1653 | } else { | ||
1654 | if (i < 13) | ||
1655 | return 0; | ||
1656 | memcpy(p, str, 12); | ||
1657 | p += 12; | ||
1658 | str += 12; | ||
1659 | i -= 12; | ||
1660 | } | ||
1661 | 1658 | ||
1662 | if (i < 1) | 1659 | memset(&tm1, 0, sizeof(tm1)); |
1663 | return 0; | ||
1664 | if ((*str == 'Z') || (*str == '-') || (*str == '+')) { | ||
1665 | *(p++) = '0'; | ||
1666 | *(p++) = '0'; | ||
1667 | } else { | ||
1668 | if (i < 2) | ||
1669 | return 0; | ||
1670 | *(p++) = *(str++); | ||
1671 | *(p++) = *(str++); | ||
1672 | i -= 2; | ||
1673 | if (i < 1) | ||
1674 | return 0; | ||
1675 | /* Skip any fractional seconds... */ | ||
1676 | if (*str == '.') { | ||
1677 | str++; | ||
1678 | i--; | ||
1679 | while (i > 1 && (*str >= '0') && (*str <= '9')) { | ||
1680 | str++; | ||
1681 | i--; | ||
1682 | } | ||
1683 | } | ||
1684 | } | ||
1685 | *(p++) = 'Z'; | ||
1686 | *(p++) = '\0'; | ||
1687 | 1660 | ||
1688 | if (i < 1) | 1661 | if (asn1_time_parse(ctm->data, ctm->length, &tm1, 0) == -1) |
1689 | return 0; | 1662 | goto out; /* invalid time */ |
1690 | if (*str == 'Z') { | ||
1691 | if (i != 1) | ||
1692 | return 0; | ||
1693 | offset = 0; | ||
1694 | } else { | ||
1695 | if (i != 5) | ||
1696 | return 0; | ||
1697 | if ((*str != '+') && (*str != '-')) | ||
1698 | return 0; | ||
1699 | if (str[1] < '0' || str[1] > '9' || | ||
1700 | str[2] < '0' || str[2] > '9' || | ||
1701 | str[3] < '0' || str[3] > '9' || | ||
1702 | str[4] < '0' || str[4] > '9') | ||
1703 | return 0; | ||
1704 | offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60; | ||
1705 | offset += (str[3] - '0') * 10 + (str[4] - '0'); | ||
1706 | if (*str == '-') | ||
1707 | offset = -offset; | ||
1708 | } | ||
1709 | atm.type = ctm->type; | ||
1710 | atm.flags = 0; | ||
1711 | atm.length = sizeof(buff2); | ||
1712 | atm.data = (unsigned char *)buff2; | ||
1713 | 1663 | ||
1714 | if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL) | 1664 | /* |
1715 | return 0; | 1665 | * Defensively fail if the time string is not representable as |
1666 | * a time_t. A time_t must be sane if you care about times after | ||
1667 | * Jan 19 2038. | ||
1668 | */ | ||
1669 | if ((time1 = timegm(&tm1)) == -1) | ||
1670 | goto out; | ||
1716 | 1671 | ||
1717 | if (ctm->type == V_ASN1_UTCTIME) { | 1672 | if (time1 <= time2) |
1718 | i = (buff1[0] - '0') * 10 + (buff1[1] - '0'); | 1673 | ret = -1; |
1719 | if (i < 50) | ||
1720 | i += 100; /* cf. RFC 2459 */ | ||
1721 | j = (buff2[0] - '0') * 10 + (buff2[1] - '0'); | ||
1722 | if (j < 50) | ||
1723 | j += 100; | ||
1724 | if (i < j) | ||
1725 | return -1; | ||
1726 | if (i > j) | ||
1727 | return 1; | ||
1728 | } | ||
1729 | i = strcmp(buff1, buff2); | ||
1730 | if (i == 0) /* wait a second then return younger :-) */ | ||
1731 | return -1; | ||
1732 | else | 1674 | else |
1733 | return i; | 1675 | ret = 1; |
1676 | out: | ||
1677 | return (ret); | ||
1734 | } | 1678 | } |
1735 | 1679 | ||
1736 | ASN1_TIME * | 1680 | ASN1_TIME * |
diff --git a/src/lib/libssl/src/crypto/asn1/a_gentm.c b/src/lib/libssl/src/crypto/asn1/a_gentm.c index 4cee40437c..594eb63058 100644 --- a/src/lib/libssl/src/crypto/asn1/a_gentm.c +++ b/src/lib/libssl/src/crypto/asn1/a_gentm.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: a_gentm.c,v 1.24 2015/09/30 18:04:02 jsing Exp $ */ | 1 | /* $OpenBSD: a_gentm.c,v 1.25 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -66,86 +66,14 @@ | |||
66 | #include <openssl/err.h> | 66 | #include <openssl/err.h> |
67 | 67 | ||
68 | #include "o_time.h" | 68 | #include "o_time.h" |
69 | #include "asn1_locl.h" | ||
69 | 70 | ||
70 | int | 71 | int |
71 | ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d) | 72 | ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d) |
72 | { | 73 | { |
73 | static const int min[9] = {0, 0, 1, 1, 0, 0, 0, 0, 0}; | ||
74 | static const int max[9] = {99, 99, 12, 31, 23, 59, 59, 12, 59}; | ||
75 | char *a; | ||
76 | int n, i, l, o; | ||
77 | |||
78 | if (d->type != V_ASN1_GENERALIZEDTIME) | 74 | if (d->type != V_ASN1_GENERALIZEDTIME) |
79 | return (0); | 75 | return (0); |
80 | l = d->length; | 76 | return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); |
81 | a = (char *)d->data; | ||
82 | o = 0; | ||
83 | /* GENERALIZEDTIME is similar to UTCTIME except the year is | ||
84 | * represented as YYYY. This stuff treats everything as a two digit | ||
85 | * field so make first two fields 00 to 99 | ||
86 | */ | ||
87 | if (l < 13) | ||
88 | goto err; | ||
89 | for (i = 0; i < 7; i++) { | ||
90 | if ((i == 6) && ((a[o] == 'Z') || | ||
91 | (a[o] == '+') || (a[o] == '-'))) { | ||
92 | i++; | ||
93 | break; | ||
94 | } | ||
95 | if ((a[o] < '0') || (a[o] > '9')) | ||
96 | goto err; | ||
97 | n= a[o]-'0'; | ||
98 | if (++o > l) | ||
99 | goto err; | ||
100 | |||
101 | if ((a[o] < '0') || (a[o] > '9')) | ||
102 | goto err; | ||
103 | n = (n * 10)+ a[o] - '0'; | ||
104 | if (++o > l) | ||
105 | goto err; | ||
106 | |||
107 | if ((n < min[i]) || (n > max[i])) | ||
108 | goto err; | ||
109 | } | ||
110 | /* Optional fractional seconds: decimal point followed by one | ||
111 | * or more digits. | ||
112 | */ | ||
113 | if (a[o] == '.') { | ||
114 | if (++o > l) | ||
115 | goto err; | ||
116 | i = o; | ||
117 | while ((a[o] >= '0') && (a[o] <= '9') && (o <= l)) | ||
118 | o++; | ||
119 | /* Must have at least one digit after decimal point */ | ||
120 | if (i == o) | ||
121 | goto err; | ||
122 | } | ||
123 | |||
124 | if (a[o] == 'Z') | ||
125 | o++; | ||
126 | else if ((a[o] == '+') || (a[o] == '-')) { | ||
127 | o++; | ||
128 | if (o + 4 > l) | ||
129 | goto err; | ||
130 | for (i = 7; i < 9; i++) { | ||
131 | if ((a[o] < '0') || (a[o] > '9')) | ||
132 | goto err; | ||
133 | n = a[o] - '0'; | ||
134 | o++; | ||
135 | if ((a[o] < '0') || (a[o] > '9')) | ||
136 | goto err; | ||
137 | n = (n * 10) + a[o] - '0'; | ||
138 | if ((n < min[i]) || (n > max[i])) | ||
139 | goto err; | ||
140 | o++; | ||
141 | } | ||
142 | } else { | ||
143 | /* Missing time zone information. */ | ||
144 | goto err; | ||
145 | } | ||
146 | return (o == l); | ||
147 | err: | ||
148 | return (0); | ||
149 | } | 77 | } |
150 | 78 | ||
151 | int | 79 | int |
@@ -179,34 +107,26 @@ ASN1_GENERALIZEDTIME_adj_internal(ASN1_GENERALIZEDTIME *s, time_t t, | |||
179 | int offset_day, long offset_sec) | 107 | int offset_day, long offset_sec) |
180 | { | 108 | { |
181 | char *p; | 109 | char *p; |
182 | struct tm *ts; | 110 | struct tm *tm; |
183 | struct tm data; | 111 | struct tm data; |
184 | size_t len = 20; | ||
185 | 112 | ||
186 | ts = gmtime_r(&t, &data); | 113 | tm = gmtime_r(&t, &data); |
187 | if (ts == NULL) | 114 | if (tm == NULL) |
188 | return (NULL); | 115 | return (NULL); |
189 | 116 | ||
190 | if (offset_day || offset_sec) { | 117 | if (offset_day || offset_sec) { |
191 | if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) | 118 | if (!OPENSSL_gmtime_adj(tm, offset_day, offset_sec)) |
192 | return NULL; | 119 | return NULL; |
193 | } | 120 | } |
194 | 121 | ||
195 | p = (char *)s->data; | 122 | if ((p = gentime_string_from_tm(tm)) == NULL) { |
196 | if ((p == NULL) || ((size_t)s->length < len)) { | 123 | ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, ERR_R_MALLOC_FAILURE); |
197 | p = malloc(len); | 124 | return (NULL); |
198 | if (p == NULL) { | ||
199 | ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, | ||
200 | ERR_R_MALLOC_FAILURE); | ||
201 | return (NULL); | ||
202 | } | ||
203 | free(s->data); | ||
204 | s->data = (unsigned char *)p; | ||
205 | } | 125 | } |
206 | 126 | free(s->data); | |
207 | snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900, | 127 | s->data = p; |
208 | ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec); | ||
209 | s->length = strlen(p); | 128 | s->length = strlen(p); |
129 | |||
210 | s->type = V_ASN1_GENERALIZEDTIME; | 130 | s->type = V_ASN1_GENERALIZEDTIME; |
211 | return (s); | 131 | return (s); |
212 | } | 132 | } |
diff --git a/src/lib/libssl/src/crypto/asn1/a_time.c b/src/lib/libssl/src/crypto/asn1/a_time.c index 25a1805640..a6c7c8e736 100644 --- a/src/lib/libssl/src/crypto/asn1/a_time.c +++ b/src/lib/libssl/src/crypto/asn1/a_time.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: a_time.c,v 1.25 2015/09/30 18:04:02 jsing Exp $ */ | 1 | /* $OpenBSD: a_time.c,v 1.26 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* ==================================================================== | 2 | /* ==================================================================== |
3 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. | 3 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. |
4 | * | 4 | * |
@@ -68,7 +68,7 @@ | |||
68 | #include <openssl/err.h> | 68 | #include <openssl/err.h> |
69 | 69 | ||
70 | #include "o_time.h" | 70 | #include "o_time.h" |
71 | 71 | #include "asn1_locl.h" | |
72 | 72 | ||
73 | const ASN1_ITEM ASN1_TIME_it = { | 73 | const ASN1_ITEM ASN1_TIME_it = { |
74 | .itype = ASN1_ITYPE_MSTRING, | 74 | .itype = ASN1_ITYPE_MSTRING, |
@@ -135,11 +135,9 @@ ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec) | |||
135 | int | 135 | int |
136 | ASN1_TIME_check(ASN1_TIME *t) | 136 | ASN1_TIME_check(ASN1_TIME *t) |
137 | { | 137 | { |
138 | if (t->type == V_ASN1_GENERALIZEDTIME) | 138 | if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME) |
139 | return ASN1_GENERALIZEDTIME_check(t); | 139 | return 0; |
140 | else if (t->type == V_ASN1_UTCTIME) | 140 | return (t->type == asn1_time_parse(t->data, t->length, NULL, t->type)); |
141 | return ASN1_UTCTIME_check(t); | ||
142 | return 0; | ||
143 | } | 141 | } |
144 | 142 | ||
145 | /* Convert an ASN1_TIME structure to GeneralizedTime */ | 143 | /* Convert an ASN1_TIME structure to GeneralizedTime */ |
@@ -210,13 +208,12 @@ ASN1_TIME_set_string(ASN1_TIME *s, const char *str) | |||
210 | t.data = (unsigned char *)str; | 208 | t.data = (unsigned char *)str; |
211 | t.flags = 0; | 209 | t.flags = 0; |
212 | 210 | ||
213 | t.type = V_ASN1_UTCTIME; | 211 | t.type = asn1_time_parse(t.data, t.length, NULL, V_ASN1_UTCTIME); |
214 | 212 | if (t.type == -1) | |
215 | if (!ASN1_TIME_check(&t)) { | 213 | t.type = asn1_time_parse(t.data, t.length, NULL, |
216 | t.type = V_ASN1_GENERALIZEDTIME; | 214 | V_ASN1_GENERALIZEDTIME); |
217 | if (!ASN1_TIME_check(&t)) | 215 | if (t.type == -1) |
218 | return 0; | 216 | return 0; |
219 | } | ||
220 | 217 | ||
221 | if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) | 218 | if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) |
222 | return 0; | 219 | return 0; |
diff --git a/src/lib/libssl/src/crypto/asn1/a_time_tm.c b/src/lib/libssl/src/crypto/asn1/a_time_tm.c new file mode 100644 index 0000000000..65f75c68cc --- /dev/null +++ b/src/lib/libssl/src/crypto/asn1/a_time_tm.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* $OpenBSD: a_time_tm.c,v 1.1 2015/10/02 15:04:45 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 | |||
18 | #include <stdio.h> | ||
19 | #include <string.h> | ||
20 | #include <time.h> | ||
21 | #include <ctype.h> | ||
22 | #include <sys/limits.h> | ||
23 | |||
24 | #include <openssl/asn1t.h> | ||
25 | #include <openssl/err.h> | ||
26 | |||
27 | #include "o_time.h" | ||
28 | #include "asn1_locl.h" | ||
29 | |||
30 | char * | ||
31 | gentime_string_from_tm(struct tm *tm) | ||
32 | { | ||
33 | char *ret = NULL; | ||
34 | int year; | ||
35 | year = tm->tm_year + 1900; | ||
36 | if (year < 0 || year > 9999) | ||
37 | return (NULL); | ||
38 | if (asprintf(&ret, "%04u%02u%02u%02u%02u%02uZ", year, | ||
39 | tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
40 | tm->tm_sec) == -1) | ||
41 | ret = NULL; | ||
42 | return (ret); | ||
43 | } | ||
44 | |||
45 | char * | ||
46 | utctime_string_from_tm(struct tm *tm) | ||
47 | { | ||
48 | char *ret = NULL; | ||
49 | if (tm->tm_year >= 150 || tm->tm_year < 50) | ||
50 | return (NULL); | ||
51 | if (asprintf(&ret, "%02u%02u%02u%02u%02u%02uZ", | ||
52 | tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, | ||
53 | tm->tm_hour, tm->tm_min, tm->tm_sec) == -1) | ||
54 | ret = NULL; | ||
55 | return (ret); | ||
56 | } | ||
57 | |||
58 | /* | ||
59 | * Parse an ASN.1 time string. | ||
60 | * | ||
61 | * mode must be: | ||
62 | * 0 if we expect to parse a time as specified in RFC 5280 from an | ||
63 | * X509 certificate. | ||
64 | * V_ASN1_UTCTIME if we wish to parse a legacy ASN1 UTC time. | ||
65 | * V_ASN1_GENERALIZEDTIME if we wish to parse a legacy ASN1 | ||
66 | * Generalizd time. | ||
67 | * | ||
68 | * Returns: | ||
69 | * -1 if the string was invalid. | ||
70 | * V_ASN1_UTCTIME if the string validated as a UTC time string. | ||
71 | * V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string. | ||
72 | * | ||
73 | * Fills in *tm with the corresponding time if tm is non NULL. | ||
74 | */ | ||
75 | #define RFC5280 0 | ||
76 | #define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0')) | ||
77 | int asn1_time_parse(const char * bytes, size_t len, struct tm *tm, int mode) | ||
78 | { | ||
79 | char *p, *buf = NULL, *dot = NULL, *tz = NULL; | ||
80 | int i, offset, noseconds = 0, type = 0; | ||
81 | struct tm ltm; | ||
82 | struct tm *lt; | ||
83 | size_t tlen; | ||
84 | char tzc; | ||
85 | |||
86 | if (bytes == NULL) | ||
87 | goto err; | ||
88 | |||
89 | if (len > INT_MAX) | ||
90 | goto err; | ||
91 | |||
92 | /* Constrain the RFC5280 case within max/min valid lengths. */ | ||
93 | if (mode == RFC5280 && (len > 15 || len < 13)) | ||
94 | goto err; | ||
95 | |||
96 | if ((buf = strndup(bytes, len)) == NULL) | ||
97 | goto err; | ||
98 | lt = tm; | ||
99 | if (lt == NULL) { | ||
100 | time_t t = time(NULL); | ||
101 | lt = gmtime_r(&t, <m); | ||
102 | if (lt == NULL) | ||
103 | goto err; | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * Find position of the optional fractional seconds, and the | ||
108 | * start of the timezone, while ensuring everything else is | ||
109 | * digits. | ||
110 | */ | ||
111 | for (i = 0; i < len; i++) { | ||
112 | char *t = buf + i; | ||
113 | if (isdigit((unsigned char)*t)) | ||
114 | continue; | ||
115 | if (*t == '.' && dot == NULL) { | ||
116 | dot = t; | ||
117 | continue; | ||
118 | } | ||
119 | if ((*t == 'Z' || *t == '+' || *t == '-') && tz == NULL) { | ||
120 | tz = t; | ||
121 | continue; | ||
122 | } | ||
123 | goto err; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Timezone is required. For the non-RFC case it may be | ||
128 | * either Z or +- HHMM, but for RFC5280 it may be only Z. | ||
129 | */ | ||
130 | if (tz == NULL) | ||
131 | goto err; | ||
132 | tzc = *tz; | ||
133 | *tz++ = '\0'; | ||
134 | if (tzc == 'Z') { | ||
135 | if (*tz != '\0') | ||
136 | goto err; | ||
137 | offset = 0; | ||
138 | } else if (mode != RFC5280 && (tzc == '+' || tzc == '-') && | ||
139 | (strlen(tz) == 4)) { | ||
140 | int hours, mins; | ||
141 | hours = ATOI2(tz); | ||
142 | mins = ATOI2(tz); | ||
143 | if (hours > 12 || mins > 59) | ||
144 | goto err; | ||
145 | offset = hours * 3600 + mins * 60; | ||
146 | if (tzc == '-') | ||
147 | offset = -offset; | ||
148 | } else | ||
149 | goto err; | ||
150 | |||
151 | if (mode != RFC5280) { | ||
152 | /* XXX - yuck - OPENSSL_gmtime_adj should go away */ | ||
153 | if (!OPENSSL_gmtime_adj(lt, 0, offset)) | ||
154 | goto err; | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * We only allow fractional seconds to be present if we are in | ||
159 | * the non-RFC case of a Generalized time. RFC 5280 forbids | ||
160 | * fractional seconds. | ||
161 | */ | ||
162 | if (dot != NULL) { | ||
163 | if (mode != V_ASN1_GENERALIZEDTIME) | ||
164 | goto err; | ||
165 | *dot++ = '\0'; | ||
166 | if (!isdigit((unsigned char)*dot)) | ||
167 | goto err; | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Validate and convert the time | ||
172 | */ | ||
173 | p = buf; | ||
174 | tlen = strlen(buf); | ||
175 | switch (tlen) { | ||
176 | case 14: | ||
177 | lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ | ||
178 | if (mode == RFC5280 || mode == V_ASN1_GENERALIZEDTIME) | ||
179 | type = V_ASN1_GENERALIZEDTIME; | ||
180 | else | ||
181 | goto err; | ||
182 | /* FALLTHROUGH */ | ||
183 | case 12: | ||
184 | if (type == 0 && mode == V_ASN1_GENERALIZEDTIME) { | ||
185 | /* | ||
186 | * In the non-RFC case of a Generalized time | ||
187 | * seconds may not have been provided. RFC | ||
188 | * 5280 mandates that seconds must be present. | ||
189 | */ | ||
190 | noseconds = 1; | ||
191 | lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ | ||
192 | type = V_ASN1_GENERALIZEDTIME; | ||
193 | } | ||
194 | /* FALLTHROUGH */ | ||
195 | case 10: | ||
196 | if (type == 0) { | ||
197 | /* | ||
198 | * At this point we must have a UTC time. | ||
199 | * In the RFC 5280 case it must have the | ||
200 | * seconds present. In the non-RFC case | ||
201 | * may have no seconds. | ||
202 | */ | ||
203 | if (mode == V_ASN1_GENERALIZEDTIME) | ||
204 | goto err; | ||
205 | if (tlen == 10) { | ||
206 | if (mode == V_ASN1_UTCTIME) | ||
207 | noseconds = 1; | ||
208 | else | ||
209 | goto err; | ||
210 | } | ||
211 | type = V_ASN1_UTCTIME; | ||
212 | } | ||
213 | lt->tm_year += ATOI2(p); /* yy */ | ||
214 | if (type == V_ASN1_UTCTIME) { | ||
215 | if (lt->tm_year < 50) | ||
216 | lt->tm_year += 100; | ||
217 | } | ||
218 | lt->tm_mon = ATOI2(p); /* mm */ | ||
219 | if ((lt->tm_mon > 12) || !lt->tm_mon) | ||
220 | goto err; | ||
221 | --lt->tm_mon; /* struct tm is 0 - 11 */ | ||
222 | lt->tm_mday = ATOI2(p); /* dd */ | ||
223 | if ((lt->tm_mday > 31) || !lt->tm_mday) | ||
224 | goto err; | ||
225 | lt->tm_hour = ATOI2(p); /* HH */ | ||
226 | if (lt->tm_hour > 23) | ||
227 | goto err; | ||
228 | lt->tm_min = ATOI2(p); /* MM */ | ||
229 | if (lt->tm_min > 59) | ||
230 | goto err; | ||
231 | lt->tm_sec = 0; /* SS */ | ||
232 | if (noseconds) | ||
233 | break; | ||
234 | lt->tm_sec = ATOI2(p); | ||
235 | /* Leap second 60 is not accepted. Reconsider later? */ | ||
236 | if (lt->tm_sec > 59) | ||
237 | goto err; | ||
238 | break; | ||
239 | default: | ||
240 | goto err; | ||
241 | } | ||
242 | |||
243 | /* RFC 5280 section 4.1.2.5 */ | ||
244 | if (mode == RFC5280 && lt->tm_year < 150 && | ||
245 | type != V_ASN1_UTCTIME) | ||
246 | goto err; | ||
247 | if (mode == RFC5280 && lt->tm_year >= 150 && | ||
248 | type != V_ASN1_GENERALIZEDTIME) | ||
249 | goto err; | ||
250 | |||
251 | free(buf); | ||
252 | return type; | ||
253 | |||
254 | err: | ||
255 | free(buf); | ||
256 | return -1; | ||
257 | } | ||
diff --git a/src/lib/libssl/src/crypto/asn1/a_utctm.c b/src/lib/libssl/src/crypto/asn1/a_utctm.c index ca19a8c7a0..c208d494c3 100644 --- a/src/lib/libssl/src/crypto/asn1/a_utctm.c +++ b/src/lib/libssl/src/crypto/asn1/a_utctm.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: a_utctm.c,v 1.28 2015/09/30 18:26:07 jsing Exp $ */ | 1 | /* $OpenBSD: a_utctm.c,v 1.29 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -64,66 +64,14 @@ | |||
64 | #include <openssl/err.h> | 64 | #include <openssl/err.h> |
65 | 65 | ||
66 | #include "o_time.h" | 66 | #include "o_time.h" |
67 | #include "asn1_locl.h" | ||
67 | 68 | ||
68 | int | 69 | int |
69 | ASN1_UTCTIME_check(ASN1_UTCTIME *d) | 70 | ASN1_UTCTIME_check(ASN1_UTCTIME *d) |
70 | { | 71 | { |
71 | static const int min[8] = {0, 1, 1, 0, 0, 0, 0, 0}; | ||
72 | static const int max[8] = {99, 12, 31, 23, 59, 59, 12, 59}; | ||
73 | char *a; | ||
74 | int n, i, l, o; | ||
75 | |||
76 | if (d->type != V_ASN1_UTCTIME) | 72 | if (d->type != V_ASN1_UTCTIME) |
77 | return (0); | 73 | return (0); |
78 | l = d->length; | 74 | return(d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); |
79 | a = (char *)d->data; | ||
80 | o = 0; | ||
81 | |||
82 | if (l < 11) | ||
83 | |||
84 | goto err; | ||
85 | for (i = 0; i < 6; i++) { | ||
86 | if ((i == 5) && ((a[o] == 'Z') || | ||
87 | (a[o] == '+') || (a[o] == '-'))) { | ||
88 | i++; | ||
89 | break; | ||
90 | } | ||
91 | if ((a[o] < '0') || (a[o] > '9')) | ||
92 | goto err; | ||
93 | n = a[o]-'0'; | ||
94 | if (++o > l) | ||
95 | goto err; | ||
96 | if ((a[o] < '0') || (a[o] > '9')) | ||
97 | goto err; | ||
98 | n = (n * 10) + a[o] - '0'; | ||
99 | if (++o > l) | ||
100 | goto err; | ||
101 | if ((n < min[i]) || (n > max[i])) | ||
102 | goto err; | ||
103 | } | ||
104 | if (a[o] == 'Z') | ||
105 | o++; | ||
106 | else if ((a[o] == '+') || (a[o] == '-')) { | ||
107 | o++; | ||
108 | if (o + 4 > l) | ||
109 | goto err; | ||
110 | for (i = 6; i < 8; i++) { | ||
111 | if ((a[o] < '0') || (a[o] > '9')) | ||
112 | goto err; | ||
113 | n = a[o] -'0'; | ||
114 | o++; | ||
115 | if ((a[o] < '0') || (a[o] > '9')) | ||
116 | goto err; | ||
117 | n = (n * 10) + a[o] - '0'; | ||
118 | if ((n < min[i]) || (n > max[i])) | ||
119 | goto err; | ||
120 | o++; | ||
121 | } | ||
122 | } | ||
123 | return (o == l); | ||
124 | |||
125 | err: | ||
126 | return (0); | ||
127 | } | 75 | } |
128 | 76 | ||
129 | int | 77 | int |
@@ -159,7 +107,6 @@ ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day, | |||
159 | char *p; | 107 | char *p; |
160 | struct tm *ts; | 108 | struct tm *ts; |
161 | struct tm data; | 109 | struct tm data; |
162 | size_t len = 20; | ||
163 | 110 | ||
164 | ts = gmtime_r(&t, &data); | 111 | ts = gmtime_r(&t, &data); |
165 | if (ts == NULL) | 112 | if (ts == NULL) |
@@ -170,23 +117,14 @@ ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day, | |||
170 | return NULL; | 117 | return NULL; |
171 | } | 118 | } |
172 | 119 | ||
173 | if ((ts->tm_year < 50) || (ts->tm_year >= 150)) | 120 | if ((p = utctime_string_from_tm(ts)) == NULL) { |
174 | return NULL; | 121 | ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE); |
175 | 122 | return (NULL); | |
176 | p = (char *)s->data; | ||
177 | if ((p == NULL) || ((size_t)s->length < len)) { | ||
178 | p = malloc(len); | ||
179 | if (p == NULL) { | ||
180 | ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE); | ||
181 | return (NULL); | ||
182 | } | ||
183 | free(s->data); | ||
184 | s->data = (unsigned char *)p; | ||
185 | } | 123 | } |
186 | 124 | free(s->data); | |
187 | snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100, | 125 | s->data = p; |
188 | ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec); | ||
189 | s->length = strlen(p); | 126 | s->length = strlen(p); |
127 | |||
190 | s->type = V_ASN1_UTCTIME; | 128 | s->type = V_ASN1_UTCTIME; |
191 | return (s); | 129 | return (s); |
192 | } | 130 | } |
diff --git a/src/lib/libssl/src/crypto/asn1/asn1_locl.h b/src/lib/libssl/src/crypto/asn1/asn1_locl.h index c6c80aa6aa..d4994c7cee 100644 --- a/src/lib/libssl/src/crypto/asn1/asn1_locl.h +++ b/src/lib/libssl/src/crypto/asn1/asn1_locl.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: asn1_locl.h,v 1.5 2014/06/12 15:49:27 deraadt Exp $ */ | 1 | /* $OpenBSD: asn1_locl.h,v 1.6 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 2006. | 3 | * project 2006. |
4 | */ | 4 | */ |
@@ -58,6 +58,10 @@ | |||
58 | 58 | ||
59 | /* Internal ASN1 structures and functions: not for application use */ | 59 | /* Internal ASN1 structures and functions: not for application use */ |
60 | 60 | ||
61 | char * gentime_string_from_tm(struct tm *tm); | ||
62 | char * utctime_string_from_tm(struct tm *tm); | ||
63 | int asn1_time_parse(const char *, size_t, struct tm *, int); | ||
64 | |||
61 | /* ASN1 print context structure */ | 65 | /* ASN1 print context structure */ |
62 | 66 | ||
63 | struct asn1_pctx_st { | 67 | struct asn1_pctx_st { |
diff --git a/src/lib/libssl/src/crypto/x509/x509_lcl.h b/src/lib/libssl/src/crypto/x509/x509_lcl.h index b16df78ad7..0c1c130d5c 100644 --- a/src/lib/libssl/src/crypto/x509/x509_lcl.h +++ b/src/lib/libssl/src/crypto/x509/x509_lcl.h | |||
@@ -57,3 +57,4 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); | 59 | int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); |
60 | int asn1_time_parse(const char *, size_t, struct tm *, int); | ||
diff --git a/src/lib/libssl/src/crypto/x509/x509_vfy.c b/src/lib/libssl/src/crypto/x509/x509_vfy.c index 8d4d15668e..c48143f351 100644 --- a/src/lib/libssl/src/crypto/x509/x509_vfy.c +++ b/src/lib/libssl/src/crypto/x509/x509_vfy.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_vfy.c,v 1.45 2015/09/14 16:13:39 jsing Exp $ */ | 1 | /* $OpenBSD: x509_vfy.c,v 1.46 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -1631,106 +1631,50 @@ X509_cmp_current_time(const ASN1_TIME *ctm) | |||
1631 | return X509_cmp_time(ctm, NULL); | 1631 | return X509_cmp_time(ctm, NULL); |
1632 | } | 1632 | } |
1633 | 1633 | ||
1634 | /* | ||
1635 | * Compare a possibly unvalidated ASN1_TIME string against a time_t | ||
1636 | * using RFC 5280 rules for the time string. If *cmp_time is NULL | ||
1637 | * the current system time is used. | ||
1638 | * | ||
1639 | * XXX NOTE that unlike what you expect a "cmp" function to do in C, | ||
1640 | * XXX this one is "special", and returns 0 for error. | ||
1641 | * | ||
1642 | * Returns: | ||
1643 | * -1 if the ASN1_time is earlier than OR the same as *cmp_time. | ||
1644 | * 1 if the ASN1_time is later than *cmp_time. | ||
1645 | * 0 on error. | ||
1646 | */ | ||
1634 | int | 1647 | int |
1635 | X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) | 1648 | X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) |
1636 | { | 1649 | { |
1637 | char *str; | 1650 | time_t time1, time2; |
1638 | ASN1_TIME atm; | 1651 | struct tm tm1; |
1639 | long offset; | 1652 | int ret = 0; |
1640 | char buff1[24], buff2[24], *p; | ||
1641 | int i, j; | ||
1642 | 1653 | ||
1643 | p = buff1; | 1654 | if (cmp_time == NULL) |
1644 | i = ctm->length; | 1655 | time2 = time(NULL); |
1645 | str = (char *)ctm->data; | 1656 | else |
1646 | if (ctm->type == V_ASN1_UTCTIME) { | 1657 | time2 = *cmp_time; |
1647 | if ((i < 11) || (i > 17)) | ||
1648 | return 0; | ||
1649 | memcpy(p, str, 10); | ||
1650 | p += 10; | ||
1651 | str += 10; | ||
1652 | i -= 10; | ||
1653 | } else { | ||
1654 | if (i < 13) | ||
1655 | return 0; | ||
1656 | memcpy(p, str, 12); | ||
1657 | p += 12; | ||
1658 | str += 12; | ||
1659 | i -= 12; | ||
1660 | } | ||
1661 | 1658 | ||
1662 | if (i < 1) | 1659 | memset(&tm1, 0, sizeof(tm1)); |
1663 | return 0; | ||
1664 | if ((*str == 'Z') || (*str == '-') || (*str == '+')) { | ||
1665 | *(p++) = '0'; | ||
1666 | *(p++) = '0'; | ||
1667 | } else { | ||
1668 | if (i < 2) | ||
1669 | return 0; | ||
1670 | *(p++) = *(str++); | ||
1671 | *(p++) = *(str++); | ||
1672 | i -= 2; | ||
1673 | if (i < 1) | ||
1674 | return 0; | ||
1675 | /* Skip any fractional seconds... */ | ||
1676 | if (*str == '.') { | ||
1677 | str++; | ||
1678 | i--; | ||
1679 | while (i > 1 && (*str >= '0') && (*str <= '9')) { | ||
1680 | str++; | ||
1681 | i--; | ||
1682 | } | ||
1683 | } | ||
1684 | } | ||
1685 | *(p++) = 'Z'; | ||
1686 | *(p++) = '\0'; | ||
1687 | 1660 | ||
1688 | if (i < 1) | 1661 | if (asn1_time_parse(ctm->data, ctm->length, &tm1, 0) == -1) |
1689 | return 0; | 1662 | goto out; /* invalid time */ |
1690 | if (*str == 'Z') { | ||
1691 | if (i != 1) | ||
1692 | return 0; | ||
1693 | offset = 0; | ||
1694 | } else { | ||
1695 | if (i != 5) | ||
1696 | return 0; | ||
1697 | if ((*str != '+') && (*str != '-')) | ||
1698 | return 0; | ||
1699 | if (str[1] < '0' || str[1] > '9' || | ||
1700 | str[2] < '0' || str[2] > '9' || | ||
1701 | str[3] < '0' || str[3] > '9' || | ||
1702 | str[4] < '0' || str[4] > '9') | ||
1703 | return 0; | ||
1704 | offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60; | ||
1705 | offset += (str[3] - '0') * 10 + (str[4] - '0'); | ||
1706 | if (*str == '-') | ||
1707 | offset = -offset; | ||
1708 | } | ||
1709 | atm.type = ctm->type; | ||
1710 | atm.flags = 0; | ||
1711 | atm.length = sizeof(buff2); | ||
1712 | atm.data = (unsigned char *)buff2; | ||
1713 | 1663 | ||
1714 | if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL) | 1664 | /* |
1715 | return 0; | 1665 | * Defensively fail if the time string is not representable as |
1666 | * a time_t. A time_t must be sane if you care about times after | ||
1667 | * Jan 19 2038. | ||
1668 | */ | ||
1669 | if ((time1 = timegm(&tm1)) == -1) | ||
1670 | goto out; | ||
1716 | 1671 | ||
1717 | if (ctm->type == V_ASN1_UTCTIME) { | 1672 | if (time1 <= time2) |
1718 | i = (buff1[0] - '0') * 10 + (buff1[1] - '0'); | 1673 | ret = -1; |
1719 | if (i < 50) | ||
1720 | i += 100; /* cf. RFC 2459 */ | ||
1721 | j = (buff2[0] - '0') * 10 + (buff2[1] - '0'); | ||
1722 | if (j < 50) | ||
1723 | j += 100; | ||
1724 | if (i < j) | ||
1725 | return -1; | ||
1726 | if (i > j) | ||
1727 | return 1; | ||
1728 | } | ||
1729 | i = strcmp(buff1, buff2); | ||
1730 | if (i == 0) /* wait a second then return younger :-) */ | ||
1731 | return -1; | ||
1732 | else | 1674 | else |
1733 | return i; | 1675 | ret = 1; |
1676 | out: | ||
1677 | return (ret); | ||
1734 | } | 1678 | } |
1735 | 1679 | ||
1736 | ASN1_TIME * | 1680 | ASN1_TIME * |