summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorbeck <>2015-10-02 15:04:45 +0000
committerbeck <>2015-10-02 15:04:45 +0000
commit61992d68f1934e7e4171e633f39fb76a4654b5a2 (patch)
tree8649498e5e9fdda4e44ebac5989504efbcc57b61 /src/lib
parent5951a0298417b41fc2a1fb4ad8a057fb9530e872 (diff)
downloadopenbsd-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.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 *