summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libcrypto/asn1/a_gentm.c106
-rw-r--r--src/lib/libcrypto/asn1/a_time.c25
-rw-r--r--src/lib/libcrypto/asn1/a_time_tm.c257
-rw-r--r--src/lib/libcrypto/asn1/a_utctm.c80
-rw-r--r--src/lib/libcrypto/asn1/asn1_locl.h6
-rw-r--r--src/lib/libcrypto/crypto/Makefile3
-rw-r--r--src/lib/libcrypto/x509/x509_lcl.h1
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.c128
-rw-r--r--src/lib/libssl/src/crypto/asn1/a_gentm.c106
-rw-r--r--src/lib/libssl/src/crypto/asn1/a_time.c25
-rw-r--r--src/lib/libssl/src/crypto/asn1/a_time_tm.c257
-rw-r--r--src/lib/libssl/src/crypto/asn1/a_utctm.c80
-rw-r--r--src/lib/libssl/src/crypto/asn1/asn1_locl.h6
-rw-r--r--src/lib/libssl/src/crypto/x509/x509_lcl.h1
-rw-r--r--src/lib/libssl/src/crypto/x509/x509_vfy.c128
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
70int 71int
71ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d) 72ASN1_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);
147err:
148 return (0);
149} 77}
150 78
151int 79int
@@ -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
73const ASN1_ITEM ASN1_TIME_it = { 73const 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)
135int 135int
136ASN1_TIME_check(ASN1_TIME *t) 136ASN1_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
30char *
31gentime_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
45char *
46utctime_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'))
77int 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, &ltm);
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
254err:
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
68int 69int
69ASN1_UTCTIME_check(ASN1_UTCTIME *d) 70ASN1_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
125err:
126 return (0);
127} 75}
128 76
129int 77int
@@ -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
61char * gentime_string_from_tm(struct tm *tm);
62char * utctime_string_from_tm(struct tm *tm);
63int asn1_time_parse(const char *, size_t, struct tm *, int);
64
61/* ASN1 print context structure */ 65/* ASN1 print context structure */
62 66
63struct asn1_pctx_st { 67struct 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
3LIB= crypto 3LIB= 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
49SRCS+= asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_bytes.c a_strnid.c 49SRCS+= asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_bytes.c a_strnid.c
50SRCS+= evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c asn_moid.c 50SRCS+= evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c asn_moid.c
51SRCS+= a_set.c 51SRCS+= a_set.c
52SRCS+= a_time_tm.c
52 53
53# bf/ 54# bf/
54SRCS+= bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c 55SRCS+= 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
59int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); 59int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet);
60int 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 */
1634int 1647int
1635X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) 1648X509_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
1736ASN1_TIME * 1680ASN1_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
70int 71int
71ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d) 72ASN1_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);
147err:
148 return (0);
149} 77}
150 78
151int 79int
@@ -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
73const ASN1_ITEM ASN1_TIME_it = { 73const 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)
135int 135int
136ASN1_TIME_check(ASN1_TIME *t) 136ASN1_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
30char *
31gentime_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
45char *
46utctime_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'))
77int 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, &ltm);
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
254err:
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
68int 69int
69ASN1_UTCTIME_check(ASN1_UTCTIME *d) 70ASN1_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
125err:
126 return (0);
127} 75}
128 76
129int 77int
@@ -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
61char * gentime_string_from_tm(struct tm *tm);
62char * utctime_string_from_tm(struct tm *tm);
63int asn1_time_parse(const char *, size_t, struct tm *, int);
64
61/* ASN1 print context structure */ 65/* ASN1 print context structure */
62 66
63struct asn1_pctx_st { 67struct 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
59int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); 59int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet);
60int 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 */
1634int 1647int
1635X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) 1648X509_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
1736ASN1_TIME * 1680ASN1_TIME *