diff options
author | beck <> | 2015-10-02 15:04:45 +0000 |
---|---|---|
committer | beck <> | 2015-10-02 15:04:45 +0000 |
commit | 61992d68f1934e7e4171e633f39fb76a4654b5a2 (patch) | |
tree | 8649498e5e9fdda4e44ebac5989504efbcc57b61 /src/lib | |
parent | 5951a0298417b41fc2a1fb4ad8a057fb9530e872 (diff) | |
download | openbsd-61992d68f1934e7e4171e633f39fb76a4654b5a2.tar.gz openbsd-61992d68f1934e7e4171e633f39fb76a4654b5a2.tar.bz2 openbsd-61992d68f1934e7e4171e633f39fb76a4654b5a2.zip |
Flense the greasy black guts of unreadble string parsing code out of three areas
in asn1 and x509 code, all dealing with an ASN1_TIME. This brings the parsing
together in one function that converts into a struct tm. While we are at it this
also brings us into conformance with RFC 5280 for times allowed in an X509 cert,
as OpenSSL is very liberal with what it allows.
input and fixes from deraadt@ jsing@ guethther@ and others.
ok krw@, guenther@, jsing@
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 * |