diff options
| author | beck <> | 2015-10-19 16:32:37 +0000 |
|---|---|---|
| committer | beck <> | 2015-10-19 16:32:37 +0000 |
| commit | 6f20e3b7bc4e6801abfde111c397198fb23a59ec (patch) | |
| tree | 1e81ee793319364cca7f490012f1e9ab19b2063d /src/lib/libcrypto/asn1/a_time_tm.c | |
| parent | f6cd556833cd27c39fdf689334d6d48f27fe533e (diff) | |
| download | openbsd-6f20e3b7bc4e6801abfde111c397198fb23a59ec.tar.gz openbsd-6f20e3b7bc4e6801abfde111c397198fb23a59ec.tar.bz2 openbsd-6f20e3b7bc4e6801abfde111c397198fb23a59ec.zip | |
Stop supporing "legcay" time formats that OpenSSL supports. Rewrite the
utctime and gentime wrappers accordingly. Along with some other cleanup.
this also removes the need for timegm.
ok bcook@ sthen@ jsing@
Diffstat (limited to 'src/lib/libcrypto/asn1/a_time_tm.c')
| -rw-r--r-- | src/lib/libcrypto/asn1/a_time_tm.c | 462 |
1 files changed, 322 insertions, 140 deletions
diff --git a/src/lib/libcrypto/asn1/a_time_tm.c b/src/lib/libcrypto/asn1/a_time_tm.c index 53443fa965..352b9159ee 100644 --- a/src/lib/libcrypto/asn1/a_time_tm.c +++ b/src/lib/libcrypto/asn1/a_time_tm.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: a_time_tm.c,v 1.5 2015/10/08 02:26:31 beck Exp $ */ | 1 | /* $OpenBSD: a_time_tm.c,v 1.6 2015/10/19 16:32:37 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2015 Bob Beck <beck@openbsd.org> | 3 | * Copyright (c) 2015 Bob Beck <beck@openbsd.org> |
| 4 | * | 4 | * |
| @@ -14,7 +14,6 @@ | |||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 16 | */ | 16 | */ |
| 17 | |||
| 18 | #include <ctype.h> | 17 | #include <ctype.h> |
| 19 | #include <limits.h> | 18 | #include <limits.h> |
| 20 | #include <stdio.h> | 19 | #include <stdio.h> |
| @@ -25,8 +24,41 @@ | |||
| 25 | #include <openssl/err.h> | 24 | #include <openssl/err.h> |
| 26 | 25 | ||
| 27 | #include "o_time.h" | 26 | #include "o_time.h" |
| 28 | #include "asn1_locl.h" | ||
| 29 | 27 | ||
| 28 | #define RFC5280 0 | ||
| 29 | #define GENTIME_LENGTH 15 | ||
| 30 | #define UTCTIME_LENGTH 13 | ||
| 31 | |||
| 32 | int | ||
| 33 | asn1_tm_cmp(struct tm *tm1, struct tm *tm2) { | ||
| 34 | if (tm1->tm_year < tm2->tm_year) | ||
| 35 | return (-1); | ||
| 36 | if (tm1->tm_year > tm2->tm_year) | ||
| 37 | return (1); | ||
| 38 | if (tm1->tm_mon < tm2->tm_mon) | ||
| 39 | return (-1); | ||
| 40 | if (tm1->tm_mon > tm2->tm_mon) | ||
| 41 | return (1); | ||
| 42 | if (tm1->tm_mday < tm2->tm_mday) | ||
| 43 | return (-1); | ||
| 44 | if (tm1->tm_mday > tm2->tm_mday) | ||
| 45 | return (1); | ||
| 46 | if (tm1->tm_hour < tm2->tm_hour) | ||
| 47 | return (-1); | ||
| 48 | if (tm1->tm_hour > tm2->tm_hour) | ||
| 49 | return (1); | ||
| 50 | if (tm1->tm_min < tm2->tm_min) | ||
| 51 | return (-1); | ||
| 52 | if (tm1->tm_min > tm2->tm_min) | ||
| 53 | return (1); | ||
| 54 | if (tm1->tm_sec < tm2->tm_sec) | ||
| 55 | return (-1); | ||
| 56 | if (tm1->tm_sec > tm2->tm_sec) | ||
| 57 | return (1); | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | /* Format a time as an RFC 5280 format Generalized time */ | ||
| 30 | char * | 62 | char * |
| 31 | gentime_string_from_tm(struct tm *tm) | 63 | gentime_string_from_tm(struct tm *tm) |
| 32 | { | 64 | { |
| @@ -45,6 +77,7 @@ gentime_string_from_tm(struct tm *tm) | |||
| 45 | return (ret); | 77 | return (ret); |
| 46 | } | 78 | } |
| 47 | 79 | ||
| 80 | /* Format a time as an RFC 5280 format UTC time */ | ||
| 48 | char * | 81 | char * |
| 49 | utctime_string_from_tm(struct tm *tm) | 82 | utctime_string_from_tm(struct tm *tm) |
| 50 | { | 83 | { |
| @@ -61,14 +94,32 @@ utctime_string_from_tm(struct tm *tm) | |||
| 61 | return (ret); | 94 | return (ret); |
| 62 | } | 95 | } |
| 63 | 96 | ||
| 97 | /* Format a time correctly for an X509 object as per RFC 5280 */ | ||
| 98 | char * | ||
| 99 | rfc5280_string_from_tm(struct tm *tm) | ||
| 100 | { | ||
| 101 | char *ret = NULL; | ||
| 102 | int year; | ||
| 103 | |||
| 104 | year = tm->tm_year + 1900; | ||
| 105 | if (year < 1950 || year > 9999) | ||
| 106 | return (NULL); | ||
| 107 | |||
| 108 | if (year < 2050) | ||
| 109 | ret = utctime_string_from_tm(tm); | ||
| 110 | else | ||
| 111 | ret = gentime_string_from_tm(tm); | ||
| 112 | |||
| 113 | return (ret); | ||
| 114 | } | ||
| 115 | |||
| 64 | /* | 116 | /* |
| 65 | * Parse an ASN.1 time string. | 117 | * Parse an RFC 5280 format ASN.1 time string. |
| 66 | * | 118 | * |
| 67 | * mode must be: | 119 | * mode must be: |
| 68 | * 0 if we expect to parse a time as specified in RFC 5280 from an | 120 | * 0 if we expect to parse a time as specified in RFC 5280 from an X509 object. |
| 69 | * X509 certificate. | 121 | * V_ASN1_UTCTIME if we wish to parse on RFC5280 format UTC time. |
| 70 | * V_ASN1_UTCTIME if we wish to parse a legacy ASN1 UTC time. | 122 | * V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time. |
| 71 | * V_ASN1_GENERALIZEDTIME if we wish to parse a legacy ASN1 Generalized time. | ||
| 72 | * | 123 | * |
| 73 | * Returns: | 124 | * Returns: |
| 74 | * -1 if the string was invalid. | 125 | * -1 if the string was invalid. |
| @@ -77,141 +128,54 @@ utctime_string_from_tm(struct tm *tm) | |||
| 77 | * | 128 | * |
| 78 | * Fills in *tm with the corresponding time if tm is non NULL. | 129 | * Fills in *tm with the corresponding time if tm is non NULL. |
| 79 | */ | 130 | */ |
| 80 | #define RFC5280 0 | ||
| 81 | #define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0')) | 131 | #define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0')) |
| 82 | int | 132 | int |
| 83 | asn1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode) | 133 | asn1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode) |
| 84 | { | 134 | { |
| 85 | char *p, *buf = NULL, *dot = NULL, *tz = NULL; | 135 | int i, type = 0; |
| 86 | int i, offset = 0, noseconds = 0, type = 0, ret = -1; | ||
| 87 | struct tm ltm; | 136 | struct tm ltm; |
| 88 | struct tm *lt; | 137 | struct tm *lt; |
| 89 | size_t tlen; | 138 | const char *p; |
| 90 | char tzc; | ||
| 91 | 139 | ||
| 92 | if (bytes == NULL) | 140 | if (bytes == NULL) |
| 93 | goto err; | 141 | return (-1); |
| 94 | |||
| 95 | if (len > INT_MAX) | ||
| 96 | goto err; | ||
| 97 | 142 | ||
| 98 | /* Constrain the RFC5280 case within min/max valid lengths. */ | 143 | /* Constrain to valid lengths. */ |
| 99 | if (mode == RFC5280 && (len < 13 || len > 15)) | 144 | if (len != UTCTIME_LENGTH && len != GENTIME_LENGTH) |
| 100 | goto err; | 145 | return (-1); |
| 101 | |||
| 102 | if ((buf = strndup(bytes, len)) == NULL) | ||
| 103 | goto err; | ||
| 104 | 146 | ||
| 105 | lt = tm; | 147 | lt = tm; |
| 106 | if (lt == NULL) { | 148 | if (lt == NULL) { |
| 107 | time_t t = time(NULL); | 149 | memset(<m, 0, sizeof(ltm)); |
| 108 | lt = gmtime_r(&t, <m); | 150 | lt = <m; |
| 109 | if (lt == NULL) | ||
| 110 | goto err; | ||
| 111 | } | 151 | } |
| 112 | 152 | ||
| 113 | /* | 153 | /* Timezone is required and must be GMT (Zulu). */ |
| 114 | * Find position of the optional fractional seconds, and the | 154 | if (bytes[len - 1] != 'Z') |
| 115 | * start of the timezone, while ensuring everything else is | 155 | return (-1); |
| 116 | * digits. | ||
| 117 | */ | ||
| 118 | for (i = 0; i < len; i++) { | ||
| 119 | char *t = buf + i; | ||
| 120 | if (isdigit((unsigned char)*t)) | ||
| 121 | continue; | ||
| 122 | if (*t == '.' && dot == NULL && tz == NULL) { | ||
| 123 | dot = t; | ||
| 124 | continue; | ||
| 125 | } | ||
| 126 | if ((*t == 'Z' || *t == '+' || *t == '-') && tz == NULL) { | ||
| 127 | tz = t; | ||
| 128 | continue; | ||
| 129 | } | ||
| 130 | goto err; | ||
| 131 | } | ||
| 132 | |||
| 133 | /* | ||
| 134 | * Timezone is required. For the non-RFC case it may be | ||
| 135 | * either Z or +- HHMM, but for RFC5280 it may be only Z. | ||
| 136 | */ | ||
| 137 | if (tz == NULL) | ||
| 138 | goto err; | ||
| 139 | tzc = *tz; | ||
| 140 | *tz++ = '\0'; | ||
| 141 | if (tzc == 'Z') { | ||
| 142 | if (*tz != '\0') | ||
| 143 | goto err; | ||
| 144 | } else if (mode != RFC5280 && (tzc == '+' || tzc == '-') && | ||
| 145 | strlen(tz) == 4) { | ||
| 146 | int hours = ATOI2(tz); | ||
| 147 | int mins = ATOI2(tz); | ||
| 148 | |||
| 149 | if (hours < 0 || hours > 12 || mins < 0 || mins > 59) | ||
| 150 | goto err; | ||
| 151 | offset = hours * 3600 + mins * 60; | ||
| 152 | if (tzc == '-') | ||
| 153 | offset = -offset; | ||
| 154 | } else | ||
| 155 | goto err; | ||
| 156 | |||
| 157 | if (offset != 0) { | ||
| 158 | /* XXX - yuck - OPENSSL_gmtime_adj should go away */ | ||
| 159 | if (!OPENSSL_gmtime_adj(lt, 0, offset)) | ||
| 160 | goto err; | ||
| 161 | } | ||
| 162 | 156 | ||
| 163 | /* | 157 | /* Make sure everything else is digits. */ |
| 164 | * We only allow fractional seconds to be present if we are in | 158 | for (i = 0; i < len - 1; i++) { |
| 165 | * the non-RFC case of a Generalized time. RFC 5280 forbids | 159 | if (isdigit((unsigned char)bytes[i])) |
| 166 | * fractional seconds. | 160 | continue; |
| 167 | */ | 161 | return (-1); |
| 168 | if (dot != NULL) { | ||
| 169 | if (mode != V_ASN1_GENERALIZEDTIME) | ||
| 170 | goto err; | ||
| 171 | *dot++ = '\0'; | ||
| 172 | if (!isdigit((unsigned char)*dot)) | ||
| 173 | goto err; | ||
| 174 | } | 162 | } |
| 175 | 163 | ||
| 176 | /* | 164 | /* |
| 177 | * Validate and convert the time | 165 | * Validate and convert the time |
| 178 | */ | 166 | */ |
| 179 | p = buf; | 167 | p = bytes; |
| 180 | tlen = strlen(buf); | 168 | switch (len) { |
| 181 | switch (tlen) { | 169 | case GENTIME_LENGTH: |
| 182 | case 14: | 170 | if (mode == V_ASN1_UTCTIME) |
| 171 | return (-1); | ||
| 183 | lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ | 172 | lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ |
| 184 | if (mode != RFC5280 && mode != V_ASN1_GENERALIZEDTIME) | ||
| 185 | goto err; | ||
| 186 | type = V_ASN1_GENERALIZEDTIME; | 173 | type = V_ASN1_GENERALIZEDTIME; |
| 187 | /* FALLTHROUGH */ | 174 | /* FALLTHROUGH */ |
| 188 | case 12: | 175 | case UTCTIME_LENGTH: |
| 189 | if (type == 0 && mode == V_ASN1_GENERALIZEDTIME) { | ||
| 190 | /* | ||
| 191 | * In the non-RFC case of a Generalized time | ||
| 192 | * seconds may not have been provided. RFC | ||
| 193 | * 5280 mandates that seconds must be present. | ||
| 194 | */ | ||
| 195 | noseconds = 1; | ||
| 196 | lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ | ||
| 197 | type = V_ASN1_GENERALIZEDTIME; | ||
| 198 | } | ||
| 199 | /* FALLTHROUGH */ | ||
| 200 | case 10: | ||
| 201 | if (type == 0) { | 176 | if (type == 0) { |
| 202 | /* | ||
| 203 | * At this point we must have a UTC time. | ||
| 204 | * In the RFC 5280 case it must have the | ||
| 205 | * seconds present. In the non-RFC case | ||
| 206 | * may have no seconds. | ||
| 207 | */ | ||
| 208 | if (mode == V_ASN1_GENERALIZEDTIME) | 177 | if (mode == V_ASN1_GENERALIZEDTIME) |
| 209 | goto err; | 178 | return (-1); |
| 210 | if (tlen == 10) { | ||
| 211 | if (mode != V_ASN1_UTCTIME) | ||
| 212 | goto err; | ||
| 213 | noseconds = 1; | ||
| 214 | } | ||
| 215 | type = V_ASN1_UTCTIME; | 179 | type = V_ASN1_UTCTIME; |
| 216 | } | 180 | } |
| 217 | lt->tm_year += ATOI2(p); /* yy */ | 181 | lt->tm_year += ATOI2(p); /* yy */ |
| @@ -221,40 +185,258 @@ asn1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode) | |||
| 221 | } | 185 | } |
| 222 | lt->tm_mon = ATOI2(p) - 1; /* mm */ | 186 | lt->tm_mon = ATOI2(p) - 1; /* mm */ |
| 223 | if (lt->tm_mon < 0 || lt->tm_mon > 11) | 187 | if (lt->tm_mon < 0 || lt->tm_mon > 11) |
| 224 | goto err; | 188 | return (-1); |
| 225 | lt->tm_mday = ATOI2(p); /* dd */ | 189 | lt->tm_mday = ATOI2(p); /* dd */ |
| 226 | if (lt->tm_mday < 1 || lt->tm_mday > 31) | 190 | if (lt->tm_mday < 1 || lt->tm_mday > 31) |
| 227 | goto err; | 191 | return (-1); |
| 228 | lt->tm_hour = ATOI2(p); /* HH */ | 192 | lt->tm_hour = ATOI2(p); /* HH */ |
| 229 | if (lt->tm_hour < 0 || lt->tm_hour > 23) | 193 | if (lt->tm_hour < 0 || lt->tm_hour > 23) |
| 230 | goto err; | 194 | return (-1); |
| 231 | lt->tm_min = ATOI2(p); /* MM */ | 195 | lt->tm_min = ATOI2(p); /* MM */ |
| 232 | if (lt->tm_hour < 0 || lt->tm_min > 59) | 196 | if (lt->tm_min < 0 || lt->tm_min > 59) |
| 233 | goto err; | 197 | return (-1); |
| 234 | lt->tm_sec = 0; /* SS */ | 198 | lt->tm_sec = ATOI2(p); /* SS */ |
| 235 | if (noseconds) | ||
| 236 | break; | ||
| 237 | lt->tm_sec = ATOI2(p); | ||
| 238 | /* Leap second 60 is not accepted. Reconsider later? */ | 199 | /* Leap second 60 is not accepted. Reconsider later? */ |
| 239 | if (lt->tm_hour < 0 || lt->tm_sec > 59) | 200 | if (lt->tm_sec < 0 || lt->tm_sec > 59) |
| 240 | goto err; | 201 | return (-1); |
| 241 | break; | 202 | break; |
| 242 | default: | 203 | default: |
| 243 | goto err; | 204 | return (-1); |
| 205 | } | ||
| 206 | |||
| 207 | return (type); | ||
| 208 | } | ||
| 209 | |||
| 210 | /* | ||
| 211 | * ASN1_TIME generic functions. | ||
| 212 | */ | ||
| 213 | |||
| 214 | static int | ||
| 215 | ASN1_TIME_set_string_internal(ASN1_TIME *s, const char *str, int mode) | ||
| 216 | { | ||
| 217 | int type; | ||
| 218 | char *tmp; | ||
| 219 | |||
| 220 | if ((type = asn1_time_parse(str, strlen(str), NULL, mode)) == -1) | ||
| 221 | return (0); | ||
| 222 | if (mode != 0 && mode != type) | ||
| 223 | return (0); | ||
| 224 | if ((tmp = strdup(str)) == NULL) | ||
| 225 | return (0); | ||
| 226 | free(s->data); | ||
| 227 | s->data = tmp; | ||
| 228 | s->length = strlen(tmp); | ||
| 229 | s->type = type; | ||
| 230 | return (1); | ||
| 231 | } | ||
| 232 | |||
| 233 | static ASN1_TIME * | ||
| 234 | ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec, | ||
| 235 | int mode) | ||
| 236 | { | ||
| 237 | int allocated = 0; | ||
| 238 | struct tm tm; | ||
| 239 | size_t len; | ||
| 240 | char * p; | ||
| 241 | |||
| 242 | if (gmtime_r(&t, &tm) == NULL) | ||
| 243 | return (NULL); | ||
| 244 | |||
| 245 | if (offset_day || offset_sec) { | ||
| 246 | if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec)) | ||
| 247 | return (NULL); | ||
| 244 | } | 248 | } |
| 245 | 249 | ||
| 246 | /* RFC 5280 section 4.1.2.5 */ | 250 | switch (mode) { |
| 247 | if (mode == RFC5280) { | 251 | case V_ASN1_UTCTIME: |
| 248 | if (lt->tm_year < 150 && type != V_ASN1_UTCTIME) | 252 | p = utctime_string_from_tm(&tm); |
| 249 | goto err; | 253 | break; |
| 250 | if (lt->tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME) | 254 | case V_ASN1_GENERALIZEDTIME: |
| 251 | goto err; | 255 | p = gentime_string_from_tm(&tm); |
| 256 | break; | ||
| 257 | case RFC5280: | ||
| 258 | p = rfc5280_string_from_tm(&tm); | ||
| 259 | break; | ||
| 260 | default: | ||
| 261 | return (NULL); | ||
| 262 | } | ||
| 263 | if (p == NULL) { | ||
| 264 | ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, | ||
| 265 | ASN1_R_ILLEGAL_TIME_VALUE); | ||
| 266 | return (NULL); | ||
| 252 | } | 267 | } |
| 253 | 268 | ||
| 254 | ret = type; | 269 | if (s == NULL) { |
| 270 | if ((s = ASN1_TIME_new()) == NULL) | ||
| 271 | return (NULL); | ||
| 272 | allocated = 1; | ||
| 273 | } | ||
| 255 | 274 | ||
| 256 | err: | 275 | len = strlen(p); |
| 257 | free(buf); | 276 | switch (len) { |
| 277 | case GENTIME_LENGTH: | ||
| 278 | s->type = V_ASN1_GENERALIZEDTIME; | ||
| 279 | break; | ||
| 280 | case UTCTIME_LENGTH: | ||
| 281 | s->type = V_ASN1_UTCTIME; | ||
| 282 | break; | ||
| 283 | default: | ||
| 284 | if (allocated) | ||
| 285 | ASN1_TIME_free(s); | ||
| 286 | free(p); | ||
| 287 | return (NULL); | ||
| 288 | } | ||
| 289 | free(s->data); | ||
| 290 | s->data = p; | ||
| 291 | s->length = len; | ||
| 292 | return (s); | ||
| 293 | } | ||
| 258 | 294 | ||
| 259 | return (ret); | 295 | ASN1_TIME * |
| 296 | ASN1_TIME_set(ASN1_TIME *s, time_t t) | ||
| 297 | { | ||
| 298 | return (ASN1_TIME_adj(s, t, 0, 0)); | ||
| 260 | } | 299 | } |
| 300 | |||
| 301 | ASN1_TIME * | ||
| 302 | ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec) | ||
| 303 | { | ||
| 304 | return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, RFC5280)); | ||
| 305 | } | ||
| 306 | |||
| 307 | int | ||
| 308 | ASN1_TIME_check(ASN1_TIME *t) | ||
| 309 | { | ||
| 310 | if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME) | ||
| 311 | return (0); | ||
| 312 | return (t->type == asn1_time_parse(t->data, t->length, NULL, t->type)); | ||
| 313 | } | ||
| 314 | |||
| 315 | ASN1_GENERALIZEDTIME * | ||
| 316 | ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) | ||
| 317 | { | ||
| 318 | ASN1_GENERALIZEDTIME *tmp = NULL; | ||
| 319 | struct tm tm; | ||
| 320 | char *str; | ||
| 321 | |||
| 322 | if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME) | ||
| 323 | return (NULL); | ||
| 324 | |||
| 325 | memset(&tm, 0, sizeof(tm)); | ||
| 326 | if (t->type != asn1_time_parse(t->data, t->length, &tm, t->type)) | ||
| 327 | return (NULL); | ||
| 328 | if ((str = gentime_string_from_tm(&tm)) == NULL) | ||
| 329 | return (NULL); | ||
| 330 | |||
| 331 | if (out != NULL) | ||
| 332 | tmp = *out; | ||
| 333 | if (tmp == NULL && (tmp = ASN1_GENERALIZEDTIME_new()) == NULL) { | ||
| 334 | free(str); | ||
| 335 | return (NULL); | ||
| 336 | } | ||
| 337 | if (out != NULL) | ||
| 338 | *out = tmp; | ||
| 339 | |||
| 340 | free(tmp->data); | ||
| 341 | tmp->data = str; | ||
| 342 | tmp->length = strlen(str); | ||
| 343 | return (tmp); | ||
| 344 | } | ||
| 345 | |||
| 346 | int | ||
| 347 | ASN1_TIME_set_string(ASN1_TIME *s, const char *str) | ||
| 348 | { | ||
| 349 | return (ASN1_TIME_set_string_internal(s, str, 0)); | ||
| 350 | } | ||
| 351 | |||
| 352 | /* | ||
| 353 | * ASN1_UTCTIME wrappers | ||
| 354 | */ | ||
| 355 | |||
| 356 | int | ||
| 357 | ASN1_UTCTIME_check(ASN1_UTCTIME *d) | ||
| 358 | { | ||
| 359 | if (d->type != V_ASN1_UTCTIME) | ||
| 360 | return (0); | ||
| 361 | return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); | ||
| 362 | } | ||
| 363 | |||
| 364 | int | ||
| 365 | ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) | ||
| 366 | { | ||
| 367 | if (s->type != V_ASN1_UTCTIME) | ||
| 368 | return (0); | ||
| 369 | return (ASN1_TIME_set_string_internal(s, str, V_ASN1_UTCTIME)); | ||
| 370 | } | ||
| 371 | |||
| 372 | ASN1_UTCTIME * | ||
| 373 | ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) | ||
| 374 | { | ||
| 375 | return (ASN1_UTCTIME_adj(s, t, 0, 0)); | ||
| 376 | } | ||
| 377 | |||
| 378 | ASN1_UTCTIME * | ||
| 379 | ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec) | ||
| 380 | { | ||
| 381 | return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, | ||
| 382 | V_ASN1_UTCTIME)); | ||
| 383 | } | ||
| 384 | |||
| 385 | int | ||
| 386 | ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t2) | ||
| 387 | { | ||
| 388 | struct tm tm1, tm2; | ||
| 389 | |||
| 390 | /* | ||
| 391 | * This function has never handled failure conditions properly | ||
| 392 | * and should be deprecated. The OpenSSL version used to | ||
| 393 | * simply follow NULL pointers on failure. BoringSSL and | ||
| 394 | * OpenSSL now make it return -2 on failure. | ||
| 395 | * | ||
| 396 | * The danger is that users of this function will not | ||
| 397 | * differentiate the -2 failure case from t1 < t2. | ||
| 398 | */ | ||
| 399 | if (asn1_time_parse(s->data, s->length, &tm1, V_ASN1_UTCTIME) == -1) | ||
| 400 | return (-2); /* XXX */ | ||
| 401 | |||
| 402 | if (gmtime_r(&t2, &tm2) == NULL) | ||
| 403 | return (-2); /* XXX */ | ||
| 404 | |||
| 405 | return asn1_tm_cmp(&tm1, &tm2); | ||
| 406 | } | ||
| 407 | |||
| 408 | /* | ||
| 409 | * ASN1_GENERALIZEDTIME wrappers | ||
| 410 | */ | ||
| 411 | |||
| 412 | int | ||
| 413 | ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d) | ||
| 414 | { | ||
| 415 | if (d->type != V_ASN1_GENERALIZEDTIME) | ||
| 416 | return (0); | ||
| 417 | return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); | ||
| 418 | } | ||
| 419 | |||
| 420 | int | ||
| 421 | ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) | ||
| 422 | { | ||
| 423 | if (s->type != V_ASN1_GENERALIZEDTIME) | ||
| 424 | return (0); | ||
| 425 | return (ASN1_TIME_set_string_internal(s, str, V_ASN1_GENERALIZEDTIME)); | ||
| 426 | } | ||
| 427 | |||
| 428 | ASN1_GENERALIZEDTIME * | ||
| 429 | ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t) | ||
| 430 | { | ||
| 431 | return (ASN1_GENERALIZEDTIME_adj(s, t, 0, 0)); | ||
| 432 | } | ||
| 433 | |||
| 434 | ASN1_GENERALIZEDTIME * | ||
| 435 | ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, | ||
| 436 | long offset_sec) | ||
| 437 | { | ||
| 438 | return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, | ||
| 439 | V_ASN1_GENERALIZEDTIME)); | ||
| 440 | } | ||
| 441 | |||
| 442 | |||
