Consolidate to a single asn1_time_from_tm() function

Add missing ASN1_TIME functions

Do some cleanup of the ASN1_TIME code.
Add ASN1_TIME_normalize() to normalize ASN1_TIME structures.
Add ASN1_TIME_compare() to compare two ASN1_TIME structures.
Add ASN1_TIME_cmp_time_t() to compare an ASN1_TIME to time_t
(generic version of ASN1_UTCTIME_cmp_time_t()).

Replace '0' .. '9' compares with isdigit()

Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2753)
This commit is contained in:
Todd Short 2017-08-04 11:24:03 +10:00 committed by Pauli
parent 2326bba0e5
commit cf37aaa335
12 changed files with 600 additions and 202 deletions

View File

@ -13,10 +13,12 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <ctype.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include <openssl/asn1.h> #include <openssl/asn1.h>
#include "asn1_locl.h" #include "asn1_locl.h"
/* This is the primary function used to parse ASN1_GENERALIZEDTIME */
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
{ {
/* wrapper around asn1_time_to_tm */ /* wrapper around asn1_time_to_tm */
@ -39,15 +41,13 @@ int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
t.data = (unsigned char *)str; t.data = (unsigned char *)str;
t.flags = 0; t.flags = 0;
if (ASN1_GENERALIZEDTIME_check(&t)) { if (!ASN1_GENERALIZEDTIME_check(&t))
if (s != NULL) { return 0;
if (!ASN1_STRING_set((ASN1_STRING *)s, str, t.length))
return 0; if (s != NULL && !ASN1_STRING_copy(s, &t))
s->type = V_ASN1_GENERALIZEDTIME; return 0;
}
return 1; return 1;
}
return 0;
} }
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
@ -60,52 +60,19 @@ ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
time_t t, int offset_day, time_t t, int offset_day,
long offset_sec) long offset_sec)
{ {
char *p;
struct tm *ts; struct tm *ts;
struct tm data; struct tm data;
const size_t len = 20;
ASN1_GENERALIZEDTIME *tmps = NULL;
if (s == NULL)
tmps = ASN1_GENERALIZEDTIME_new();
else
tmps = s;
if (tmps == NULL)
return NULL;
ts = OPENSSL_gmtime(&t, &data); ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL) if (ts == NULL)
goto err; return NULL;
if (offset_day || offset_sec) { if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
goto err; return NULL;
} }
p = (char *)tmps->data; return asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME);
if ((p == NULL) || ((size_t)tmps->length < len)) {
p = OPENSSL_malloc(len);
if (p == NULL) {
ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_free(tmps->data);
tmps->data = (unsigned char *)p;
}
tmps->length = BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ",
ts->tm_year + 1900, ts->tm_mon + 1,
ts->tm_mday, ts->tm_hour, ts->tm_min,
ts->tm_sec);
tmps->type = V_ASN1_GENERALIZEDTIME;
#ifdef CHARSET_EBCDIC_not
ebcdic2ascii(tmps->data, tmps->data, tmps->length);
#endif
return tmps;
err:
if (s == NULL)
ASN1_GENERALIZEDTIME_free(tmps);
return NULL;
} }
int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)

View File

@ -9,6 +9,7 @@
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
#include <ctype.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include <openssl/buffer.h> #include <openssl/buffer.h>
#include <openssl/asn1.h> #include <openssl/asn1.h>
@ -84,7 +85,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
c = *(p++); c = *(p++);
if ((c == ' ') || (c == '.')) if ((c == ' ') || (c == '.'))
break; break;
if ((c < '0') || (c > '9')) { if (!isdigit(c)) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT); ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT);
goto err; goto err;
} }

View File

@ -16,6 +16,7 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <ctype.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include <openssl/asn1t.h> #include <openssl/asn1t.h>
#include "asn1_locl.h" #include "asn1_locl.h"
@ -24,6 +25,13 @@ IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
static int is_utc(const int year)
{
if (50 <= year && year <= 149)
return 1;
return 0;
}
static int leap_year(const int year) static int leap_year(const int year)
{ {
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
@ -116,14 +124,14 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
i++; i++;
break; break;
} }
if ((a[o] < '0') || (a[o] > '9')) if (!isdigit(a[o]))
goto err; goto err;
n = a[o] - '0'; n = a[o] - '0';
/* incomplete 2-digital number */ /* incomplete 2-digital number */
if (++o == l) if (++o == l)
goto err; goto err;
if ((a[o] < '0') || (a[o] > '9')) if (!isdigit(a[o]))
goto err; goto err;
n = (n * 10) + a[o] - '0'; n = (n * 10) + a[o] - '0';
/* no more bytes to read, but we haven't seen time-zone yet */ /* no more bytes to read, but we haven't seen time-zone yet */
@ -184,7 +192,7 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
if (++o == l) if (++o == l)
goto err; goto err;
i = o; i = o;
while ((o < l) && (a[o] >= '0') && (a[o] <= '9')) while ((o < l) && isdigit(a[o]))
o++; o++;
/* Must have at least one digit after decimal point */ /* Must have at least one digit after decimal point */
if (i == o) if (i == o)
@ -215,11 +223,11 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
if (o + 4 != l) if (o + 4 != l)
goto err; goto err;
for (i = end; i < end + 2; i++) { for (i = end; i < end + 2; i++) {
if ((a[o] < '0') || (a[o] > '9')) if (!isdigit(a[o]))
goto err; goto err;
n = a[o] - '0'; n = a[o] - '0';
o++; o++;
if ((a[o] < '0') || (a[o] > '9')) if (!isdigit(a[o]))
goto err; goto err;
n = (n * 10) + a[o] - '0'; n = (n * 10) + a[o] - '0';
i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i; i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
@ -250,6 +258,58 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
return 0; return 0;
} }
ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type)
{
char* p;
ASN1_TIME *tmps = NULL;
const size_t len = 20;
if (type == V_ASN1_UNDEF) {
if (is_utc(ts->tm_year))
type = V_ASN1_UTCTIME;
else
type = V_ASN1_GENERALIZEDTIME;
} else if (type == V_ASN1_UTCTIME) {
if (!is_utc(ts->tm_year))
goto err;
} else if (type != V_ASN1_GENERALIZEDTIME) {
goto err;
}
if (s == NULL)
tmps = ASN1_STRING_new();
else
tmps = s;
if (tmps == NULL)
return NULL;
if (!ASN1_STRING_set(tmps, NULL, len))
goto err;
tmps->type = type;
p = (char*)tmps->data;
if (type == V_ASN1_GENERALIZEDTIME)
tmps->length = BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ",
ts->tm_year + 1900, ts->tm_mon + 1,
ts->tm_mday, ts->tm_hour, ts->tm_min,
ts->tm_sec);
else
tmps->length = BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ",
ts->tm_year % 100, ts->tm_mon + 1,
ts->tm_mday, ts->tm_hour, ts->tm_min,
ts->tm_sec);
#ifdef CHARSET_EBCDIC_not
ebcdic2ascii(tmps->data, tmps->data, tmps->length);
#endif
return tmps;
err:
if (tmps != s)
ASN1_STRING_free(tmps);
return NULL;
}
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
{ {
return ASN1_TIME_adj(s, t, 0, 0); return ASN1_TIME_adj(s, t, 0, 0);
@ -270,9 +330,7 @@ ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
return NULL; return NULL;
} }
if ((ts->tm_year >= 50) && (ts->tm_year < 150)) return asn1_time_from_tm(s, ts, V_ASN1_UNDEF);
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
} }
int ASN1_TIME_check(const ASN1_TIME *t) int ASN1_TIME_check(const ASN1_TIME *t)
@ -289,71 +347,28 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out) ASN1_GENERALIZEDTIME **out)
{ {
ASN1_GENERALIZEDTIME *ret = NULL; ASN1_GENERALIZEDTIME *ret = NULL;
char *str; struct tm tm;
if (!ASN1_TIME_check(t)) if (!ASN1_TIME_to_tm(t, &tm))
return NULL; return NULL;
if (out == NULL || *out == NULL) { if (out != NULL)
if ((ret = ASN1_GENERALIZEDTIME_new()) == NULL)
goto err;
} else {
ret = *out; ret = *out;
}
/* If already GeneralizedTime just copy across */ ret = asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME);
if (t->type == V_ASN1_GENERALIZEDTIME) {
if (!ASN1_STRING_set(ret, t->data, t->length))
goto err;
goto done;
}
/* if (out != NULL && ret != NULL)
* Grow the string by two bytes. *out = ret;
* The actual allocation is t->length + 3 to include a terminator byte.
*/
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
goto err;
str = (char *)ret->data;
/* Work out the century and prepend */
memcpy(str, t->data[0] >= '5' ? "19" : "20", 2);
/*
* t->length + 1 is the size of the data and the allocated buffer has
* this much space after the first two characters.
*/
OPENSSL_strlcpy(str + 2, (const char *)t->data, t->length + 1);
done: return ret;
if (out != NULL && *out == NULL)
*out = ret;
return ret;
err:
if (out == NULL || *out != ret)
ASN1_GENERALIZEDTIME_free(ret);
return NULL;
} }
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{ {
ASN1_TIME t; /* Try UTC, if that fails, try GENERALIZED */
if (ASN1_UTCTIME_set_string(s, str))
t.length = strlen(str); return 1;
t.data = (unsigned char *)str; return ASN1_GENERALIZEDTIME_set_string(s, str);
t.flags = 0;
t.type = V_ASN1_UTCTIME;
if (!ASN1_TIME_check(&t)) {
t.type = V_ASN1_GENERALIZEDTIME;
if (!ASN1_TIME_check(&t))
return 0;
}
if (s != NULL && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
return 0;
return 1;
} }
int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str) int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
@ -391,7 +406,7 @@ int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) { if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) {
if (!asn1_time_to_tm(&tm, &t)) if (!asn1_time_to_tm(&tm, &t))
goto out; goto out;
if (tm.tm_year >= 50 && tm.tm_year < 150) { if (is_utc(tm.tm_year)) {
t.length -= 2; t.length -= 2;
/* /*
* it's OK to let original t.data go since that's assigned * it's OK to let original t.data go since that's assigned
@ -474,7 +489,7 @@ int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
if (tm->length > 15 && v[14] == '.') { if (tm->length > 15 && v[14] == '.') {
f = &v[14]; f = &v[14];
f_len = 1; f_len = 1;
while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9') while (14 + f_len < l && isdigit(f[f_len]))
++f_len; ++f_len;
} }
@ -492,3 +507,47 @@ int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
BIO_write(bp, "Bad time value", 14); BIO_write(bp, "Bad time value", 14);
return 0; return 0;
} }
int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
{
struct tm stm, ttm;
int day, sec;
if (!ASN1_TIME_to_tm(s, &stm))
return -2;
if (!OPENSSL_gmtime(&t, &ttm))
return -2;
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
return -2;
if (day > 0 || sec > 0)
return 1;
if (day < 0 || sec < 0)
return -1;
return 0;
}
int ASN1_TIME_normalize(ASN1_TIME *t)
{
struct tm tm;
if (!ASN1_TIME_to_tm(t, &tm))
return 0;
return asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL;
}
int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b)
{
int day, sec;
if (!ASN1_TIME_diff(&day, &sec, a, b))
return -2;
if (day > 0 || sec > 0)
return 1;
if (day < 0 || sec < 0)
return -1;
return 0;
}

View File

@ -9,10 +9,12 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <ctype.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include <openssl/asn1.h> #include <openssl/asn1.h>
#include "asn1_locl.h" #include "asn1_locl.h"
/* This is the primary function used to parse ASN1_UTCTIME */
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d) int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
{ {
/* wrapper around ans1_time_to_tm */ /* wrapper around ans1_time_to_tm */
@ -26,6 +28,7 @@ int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
return asn1_utctime_to_tm(NULL, d); return asn1_utctime_to_tm(NULL, d);
} }
/* Sets the string via simple copy without cleaning it up */
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
{ {
ASN1_UTCTIME t; ASN1_UTCTIME t;
@ -35,15 +38,13 @@ int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
t.data = (unsigned char *)str; t.data = (unsigned char *)str;
t.flags = 0; t.flags = 0;
if (ASN1_UTCTIME_check(&t)) { if (!ASN1_UTCTIME_check(&t))
if (s != NULL) { return 0;
if (!ASN1_STRING_set((ASN1_STRING *)s, str, t.length))
return 0; if (s != NULL && !ASN1_STRING_copy(s, &t))
s->type = V_ASN1_UTCTIME; return 0;
}
return 1; return 1;
}
return 0;
} }
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
@ -54,54 +55,19 @@ ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
int offset_day, long offset_sec) int offset_day, long offset_sec)
{ {
char *p;
struct tm *ts; struct tm *ts;
struct tm data; struct tm data;
const size_t len = 20;
int free_s = 0;
if (s == NULL) {
s = ASN1_UTCTIME_new();
if (s == NULL)
goto err;
free_s = 1;
}
ts = OPENSSL_gmtime(&t, &data); ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL) if (ts == NULL)
goto err; return NULL;
if (offset_day || offset_sec) { if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
goto err; return NULL;
} }
if ((ts->tm_year < 50) || (ts->tm_year >= 150)) return asn1_time_from_tm(s, ts, V_ASN1_UTCTIME);
goto err;
p = (char *)s->data;
if ((p == NULL) || ((size_t)s->length < len)) {
p = OPENSSL_malloc(len);
if (p == NULL) {
ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_free(s->data);
s->data = (unsigned char *)p;
}
s->length = BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ",
ts->tm_year % 100, ts->tm_mon + 1, ts->tm_mday,
ts->tm_hour, ts->tm_min, ts->tm_sec);
s->type = V_ASN1_UTCTIME;
#ifdef CHARSET_EBCDIC_not
ebcdic2ascii(s->data, s->data, s->length);
#endif
return s;
err:
if (free_s)
ASN1_UTCTIME_free(s);
return NULL;
} }
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
@ -118,13 +84,9 @@ int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm)) if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
return -2; return -2;
if (day > 0) if (day > 0 || sec > 0)
return 1; return 1;
if (day < 0) if (day < 0 || sec < 0)
return -1;
if (sec > 0)
return 1;
if (sec < 0)
return -1; return -1;
return 0; return 0;
} }

View File

@ -78,3 +78,5 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
/* Internal functions used by x_int64.c */ /* Internal functions used by x_int64.c */
int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len); int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len);
int i2c_uint64_int(unsigned char *p, uint64_t r, int neg); int i2c_uint64_int(unsigned char *p, uint64_t r, int neg);
ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type);

View File

@ -2,41 +2,82 @@
=head1 NAME =head1 NAME
ASN1_TIME_set, ASN1_TIME_adj, ASN1_TIME_check, ASN1_TIME_set, ASN1_UTCTIME_set, ASN1_GENERALIZEDTIME_set,
ASN1_TIME_set_string, ASN1_TIME_set_string_X509, ASN1_TIME_adj, ASN1_UTCTIME_adj, ASN1_GENERALIZEDTIME_adj,
ASN1_TIME_print, ASN1_TIME_to_tm, ASN1_TIME_diff - ASN.1 Time functions ASN1_TIME_check, ASN1_UTCTIME_check, ASN1_GENERALIZEDTIME_check,
ASN1_TIME_set_string, ASN1_UTCTIME_set_string, ASN1_GENERALIZEDTIME_set_string,
ASN1_TIME_set_string_X509,
ASN1_TIME_normalize,
ASN1_TIME_to_tm,
ASN1_TIME_print, ASN1_UTCTIME_print, ASN1_GENERALIZEDTIME_print,
ASN1_TIME_diff,
ASN1_TIME_cmp_time_t, ASN1_UTCTIME_cmp_time_t,
ASN1_TIME_compare,
ASN1_TIME_to_generalizedtime - ASN.1 Time functions
=head1 SYNOPSIS =head1 SYNOPSIS
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t); ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t);
int offset_day, long offset_sec); ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
time_t t);
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day,
long offset_sec);
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
int offset_day, long offset_sec);
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
time_t t, int offset_day,
long offset_sec);
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str); int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str); int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str);
int ASN1_TIME_check(const ASN1_TIME *t); int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
int ASN1_TIME_print(BIO *b, const ASN1_TIME *s); int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s,
int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm); const char *str);
int ASN1_TIME_diff(int *pday, int *psec, int ASN1_TIME_normalize(ASN1_TIME *s);
const ASN1_TIME *from, const ASN1_TIME *to);
int ASN1_TIME_check(const ASN1_TIME *t);
int ASN1_UTCTIME_check(const ASN1_UTCTIME *t);
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *t);
int ASN1_TIME_print(BIO *b, const ASN1_TIME *s);
int ASN1_UTCTIME_print(BIO *b, const ASN1_UTCTIME *s);
int ASN1_GENERALIZEDTIME_print(BIO *b, const ASN1_GENERALIZEDTIME *s);
int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm);
int ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from,
const ASN1_TIME *to);
int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t);
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b);
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out);
=head1 DESCRIPTION =head1 DESCRIPTION
The function ASN1_TIME_set() sets the ASN1_TIME structure B<s> to the The ASN1_TIME_set(), ASN1_UTCTIME_set() and ASN1_GENERALIZEDTIME_set()
time represented by the time_t value B<t>. If B<s> is NULL a new ASN1_TIME functions set the structure B<s> to the time represented by the time_t
structure is allocated and returned. value B<t>. If B<s> is NULL a new time structure is allocated and returned.
ASN1_TIME_adj() sets the ASN1_TIME structure B<s> to the time represented The ASN1_TIME_adj(), ASN1_UTCTIME_adj() and ASN1_GENERALIZEDTIME_adj()
functions set the time structure B<s> to the time represented
by the time B<offset_day> and B<offset_sec> after the time_t value B<t>. by the time B<offset_day> and B<offset_sec> after the time_t value B<t>.
The values of B<offset_day> or B<offset_sec> can be negative to set a The values of B<offset_day> or B<offset_sec> can be negative to set a
time before B<t>. The B<offset_sec> value can also exceed the number of time before B<t>. The B<offset_sec> value can also exceed the number of
seconds in a day. If B<s> is NULL a new ASN1_TIME structure is allocated seconds in a day. If B<s> is NULL a new structure is allocated
and returned. and returned.
ASN1_TIME_set_string() sets ASN1_TIME structure B<s> to the time The ASN1_TIME_set_string(), ASN1_UTCTIME_set_string() and
represented by string B<str> which must be in appropriate ASN.1 time ASN1_GENERALIZEDTIME_set_string() functions set the time structure B<s>
format (for example YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ). If B<s> is NULL to the time represented by string B<str> which must be in appropriate ASN.1
this function performs a format check on B<str> only. time format (for example YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ). If B<s> is NULL
this function performs a format check on B<str> only. The string B<str>
is copied into B<s>.
ASN1_TIME_set_string_X509() sets ASN1_TIME structure B<s> to the time ASN1_TIME_set_string_X509() sets ASN1_TIME structure B<s> to the time
represented by string B<str> which must be in appropriate time format represented by string B<str> which must be in appropriate time format
@ -45,13 +86,21 @@ YYYYMMDDHHMMSSZ (leap second is rejected), all other ASN.1 time format
are not allowed. If B<s> is NULL this function performs a format check are not allowed. If B<s> is NULL this function performs a format check
on B<str> only. on B<str> only.
ASN1_TIME_check() checks the syntax of ASN1_TIME structure B<s>. The ASN1_TIME_normalize() function converts an ASN1_GENERALIZEDTIME or
ASN1_UTCTIME into a time value that can be used in a certificate. It
should be used after the ASN1_TIME_set_string() functions and before
ASN1_TIME_print() functions to get consistent (i.e. GMT) results.
ASN1_TIME_print() prints out the time B<s> to BIO B<b> in human readable The ASN1_TIME_check(), ASN1_UTCTIME_check() and ASN1_GENERALIZEDTIME_check()
functions check the syntax of the time structure B<s>.
The ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
functions print the time structure B<s> to BIO B<b> in human readable
format. It will be of the format MMM DD HH:MM:SS YYYY [GMT], for example format. It will be of the format MMM DD HH:MM:SS YYYY [GMT], for example
"Feb 3 00:55:52 2015 GMT" it does not include a newline. If the time "Feb 3 00:55:52 2015 GMT" it does not include a newline. If the time
structure has invalid format it prints out "Bad time value" and returns structure has invalid format it prints out "Bad time value" and returns
an error. an error. The output for generalized time may include a fractional part
following the second.
ASN1_TIME_to_tm() converts the time B<s> to the standard B<tm> structure. ASN1_TIME_to_tm() converts the time B<s> to the standard B<tm> structure.
If B<s> is NULL, then the current time is converted. The output time is GMT. If B<s> is NULL, then the current time is converted. The output time is GMT.
@ -72,6 +121,16 @@ If both B<*pday> and B<*psec> are non-zero they will always have the same
sign. The value of B<*psec> will always be less than the number of seconds sign. The value of B<*psec> will always be less than the number of seconds
in a day. If B<from> or B<to> is NULL the current time is used. in a day. If B<from> or B<to> is NULL the current time is used.
The ASN1_TIME_cmp_time_t() and ASN1_UTCTIME_cmp_time_t() functions compare
the two times represented by the time structure B<s> and the time_t B<t>.
The ASN1_TIME_compare() function compares the two times represented by the
time structures B<a> and B<b>.
The ASN1_TIME_to_generalizedtime() function converts an ASN1_TIME to an
ASN1_GENERALIZEDTIME, regardless of year. If either B<out> or
B<*out> are NULL, then a new object is allocated and must be freed after use.
=head1 NOTES =head1 NOTES
The ASN1_TIME structure corresponds to the ASN.1 structure B<Time> The ASN1_TIME structure corresponds to the ASN.1 structure B<Time>
@ -79,13 +138,15 @@ defined in RFC5280 et al. The time setting functions obey the rules outlined
in RFC5280: if the date can be represented by UTCTime it is used, else in RFC5280: if the date can be represented by UTCTime it is used, else
GeneralizedTime is used. GeneralizedTime is used.
The ASN1_TIME structure is represented as an ASN1_STRING internally and can The ASN1_TIME, ASN1_UTCTIME and ASN1_GENERALIZEDTIME structures are represented
be freed up using ASN1_STRING_free(). as an ASN1_STRING internally and can be freed up using ASN1_STRING_free().
The ASN1_TIME structure can represent years from 0000 to 9999 but no attempt The ASN1_TIME structure can represent years from 0000 to 9999 but no attempt
is made to correct ancient calendar changes (for example from Julian to is made to correct ancient calendar changes (for example from Julian to
Gregorian calendars). Gregorian calendars).
ASN1_UTCTIME is limited to a year range of 1950 through 2049.
Some applications add offset times directly to a time_t value and pass the Some applications add offset times directly to a time_t value and pass the
results to ASN1_TIME_set() (or equivalent). This can cause problems as the results to ASN1_TIME_set() (or equivalent). This can cause problems as the
time_t value can overflow on some systems resulting in unexpected results. time_t value can overflow on some systems resulting in unexpected results.
@ -93,11 +154,24 @@ New applications should use ASN1_TIME_adj() instead and pass the offset value
in the B<offset_sec> and B<offset_day> parameters instead of directly in the B<offset_sec> and B<offset_day> parameters instead of directly
manipulating a time_t value. manipulating a time_t value.
ASN1_TIME_adj() may change the type from ASN1_GENERALIZEDTIME to ASN1_UTCTIME,
or vise-versa, based on the resulting year. The ASN1_GENERALIZEDTIME_adj() and
ASN1_UTCTIME_adj() functions will not modify the type of the return structure.
It is recommended that functions starting with ASN1_TIME be used instead of
those starting with ASN1_UTCTIME or ASN1_GENERALIZEDTIME. The functions
starting with ASN1_UTCTIME and ASN1_GENERALIZEDTIME act only on that specific
time format. The functions starting with ASN1_TIME will operate on either
format.
=head1 BUGS =head1 BUGS
ASN1_TIME_print() currently does not print out the time zone: it either prints ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
out "GMT" or nothing. But all certificates complying with RFC5280 et al use GMT do not print out the time zone: it either prints out "GMT" or nothing. But all
anyway. certificates complying with RFC5280 et al use GMT anyway.
Use the ASN1_TIME_normalize() function to normalize the time value before
printing to get GMT results.
=head1 EXAMPLES =head1 EXAMPLES
@ -133,28 +207,44 @@ Determine if one time is later or sooner than the current time:
=head1 RETURN VALUES =head1 RETURN VALUES
ASN1_TIME_set() and ASN1_TIME_adj() return a pointer to an ASN1_TIME structure ASN1_TIME_set(), ASN1_UTCTIME_set(), ASN1_GENERALIZEDTIME_set(), ASN1_TIME_adj(),
ASN1_UTCTIME_adj and ASN1_GENERALIZEDTIME_set return a pointer to a time structure
or NULL if an error occurred. or NULL if an error occurred.
ASN1_TIME_set_string() and ASN1_TIME_set_string_X509() return 1 if the time ASN1_TIME_set_string(), ASN1_UTCTIME_set_string(), ASN1_GENERALIZEDTIME_set_string()
value is successfully set and 0 otherwise. ASN1_TIME_set_string_X509() return 1 if the time value is successfully set and 0 otherwise.
ASN1_TIME_check() returns 1 if the structure is syntactically correct and 0 ASN1_TIME_normalize() returns 1 on success, and 0 on error.
otherwise.
ASN1_TIME_print() returns 1 if the time is successfully printed out and 0 if ASN1_TIME_check(), ASN1_UTCTIME_check and ASN1_GENERALIZEDTIME_check() return 1
an error occurred (I/O error or invalid time format). if the structure is syntactically correct and 0 otherwise.
ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print() return 1
if the time is successfully printed out and 0 if an error occurred (I/O error or
invalid time format).
ASN1_TIME_to_tm() returns 1 if the time is successfully parsed and 0 if an ASN1_TIME_to_tm() returns 1 if the time is successfully parsed and 0 if an
error occured (invalid time format). error occured (invalid time format).
ASN1_TIME_diff() returns 1 for success and 0 for failure. It can fail if the ASN1_TIME_diff() returns 1 for success and 0 for failure. It can fail if the
pass ASN1_TIME structure has invalid syntax for example. passed-in time structure has invalid syntax, for example.
ASN1_TIME_cmp_time_t() and ASN1_UTCTIME_cmp_time_t() return -1 if B<s> is
before B<t>, 0 if B<s> equals B<t>, or 1 if B<s> is after B<t>. -2 is returned
on error.
ASN1_TIME_compare() returns -1 if B<a> is before B<b>, 0 if B<a> equals B<b>, or 1 if B<a> is after B<b>. -2 is returned on error.
ASN1_TIME_to_generalizedtime() returns a pointer to
the appropriate time structure on success or NULL if an error occurred.
=head1 HISTORY =head1 HISTORY
The ASN1_TIME_to_tm() function was added in OpenSSL 1.1.1. The ASN1_TIME_to_tm() function was added in OpenSSL 1.1.1.
The ASN1_TIME_set_string_X509() function was added in OpenSSL 1.1.1. The ASN1_TIME_set_string_X509() function was added in OpenSSL 1.1.1.
The ASN1_TIME_normalize() function was added in OpenSSL 1.1.1.
The ASN1_TIME_cmp_time_t() function was added in OpenSSL 1.1.1.
The ASN1_TIME_compare() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT =head1 COPYRIGHT

View File

@ -590,6 +590,7 @@ ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
time_t t, int offset_day, time_t t, int offset_day,
long offset_sec); long offset_sec);
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str); int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str);
int ASN1_TIME_diff(int *pday, int *psec, int ASN1_TIME_diff(int *pday, int *psec,
const ASN1_TIME *from, const ASN1_TIME *to); const ASN1_TIME *from, const ASN1_TIME *to);
@ -632,6 +633,9 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str); int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str); int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str);
int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm); int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm);
int ASN1_TIME_normalize(ASN1_TIME *s);
int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t);
int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b);
int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a); int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a);
int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size); int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size);

296
test/asn1_time_test.c Normal file
View File

@ -0,0 +1,296 @@
/*
* Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Time tests for the asn1 module */
#include <stdio.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include "testutil.h"
#include "e_os.h"
struct testdata {
char *data; /* TIME string value */
int type; /* GENERALIZED OR UTC */
int expected_type; /* expected type after set/set_string_gmt */
int check_result; /* check result */
time_t t; /* expected time_t*/
int cmp_result; /* compariston to baseline result */
int convert_result; /* convertion result */
};
static struct testdata tbl_testdata_pos[] = {
{ "0", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, }, /* Bad time */
{ "ABCD", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "0ABCD", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "1-700101000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "`9700101000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "19700101000000Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 0, 0, 0, 0, },
{ "A00101000000Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 0, 0, 0, 0, },
{ "A9700101000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "1A700101000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "19A00101000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "197A0101000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "1970A101000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "19700A01000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "197001A1000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "1970010A000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "19700101A00000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "197001010A0000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "1970010100A000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "19700101000A00Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "197001010000A0Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "1970010100000AZ", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "700101000000X", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 0, 0, 0, 0, },
{ "19700101000000X", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 0, 0, 0, 0, },
{ "19700101000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 0, -1, 1, }, /* Epoch begins */
{ "700101000000Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 0, -1, 1, }, /* ditto */
{ "20380119031407Z", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 0x7FFFFFFF, 1, 1, }, /* Max 32bit time_t */
{ "380119031407Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 0x7FFFFFFF, 1, 1, },
{ "20371231235959Z", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 2145916799, 1, 1, }, /* Just before 2038 */
{ "20371231235959Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 0, 0, 0, 1, }, /* Bad UTC time */
{ "371231235959Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 2145916799, 1, 1, },
{ "19701006121456Z", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 24063296, -1, 1, },
{ "701006121456Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 24063296, -1, 1, },
{ "19991231000000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, }, /* Match baseline */
{ "199912310000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, }, /* In various flavors */
{ "991231000000Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
{ "9912310000Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
{ "9912310000+0000", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
{ "199912310000+0000", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
{ "9912310000-0000", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
{ "199912310000-0000", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
{ "199912310100+0100", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
{ "199912302300-0100", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
{ "199912302300-A000", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 0, 946598400, 0, 1, },
{ "199912302300-0A00", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 0, 946598400, 0, 1, },
{ "9912310100+0100", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
{ "9912302300-0100", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 946598400, 0, 1, },
};
/* ASSUMES SIGNED TIME_T */
static struct testdata tbl_testdata_neg[] = {
{ "19011213204552Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 1, -2147483648, -1, 0, },
{ "691006121456Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, -7472704, -1, 1, },
{ "19691006121456Z", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, -7472704, -1, 1, },
};
static struct testdata tbl_testdata_pos_64bit[] = {
{ "20380119031408Z", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 0x80000000, 1, 1, },
{ "20380119031409Z", V_ASN1_GENERALIZEDTIME, V_ASN1_UTCTIME, 1, 0x80000001, 1, 1, },
{ "380119031408Z", V_ASN1_UTCTIME, V_ASN1_UTCTIME, 1, 0x80000000, 1, 1, },
{ "20500101120000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 1, 2524651200, 1, 0, },
};
/* ASSUMES SIGNED TIME_T */
static struct testdata tbl_testdata_neg_64bit[] = {
{ "19011213204551Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 1, -2147483649, -1, 0, },
{ "19000101120000Z", V_ASN1_GENERALIZEDTIME, V_ASN1_GENERALIZEDTIME, 1, -2208945600, -1, 0, },
};
/* A baseline time to compare to */
static ASN1_TIME gtime = {
15,
V_ASN1_GENERALIZEDTIME,
(unsigned char*)"19991231000000Z",
0
};
static time_t gtime_t = 946598400;
static int test_table(struct testdata *tbl, int idx)
{
int error = 0;
ASN1_TIME atime;
ASN1_TIME *ptime;
struct testdata *td = &tbl[idx];
int day, sec;
atime.data = (unsigned char*)td->data;
atime.length = strlen((char*)atime.data);
atime.type = td->type;
atime.flags = 0;
if (!TEST_int_eq(ASN1_TIME_check(&atime), td->check_result)) {
TEST_info("ASN1_TIME_check(%s) unexpected result", atime.data);
error = 1;
}
if (td->check_result == 0)
return 1;
if (!TEST_int_eq(ASN1_TIME_cmp_time_t(&atime, td->t), 0)) {
TEST_info("ASN1_TIME_cmp_time_t(%s vs %ld) compare failed", atime.data, (long)td->t);
error = 1;
}
if (!TEST_true(ASN1_TIME_diff(&day, &sec, &atime, &atime))) {
TEST_info("ASN1_TIME_diff(%s) to self failed", atime.data);
error = 1;
}
if (!TEST_int_eq(day, 0) || !TEST_int_eq(sec, 0)) {
TEST_info("ASN1_TIME_diff(%s) to self not equal", atime.data);
error = 1;
}
if (!TEST_true(ASN1_TIME_diff(&day, &sec, &gtime, &atime))) {
TEST_info("ASN1_TIME_diff(%s) to baseline failed", atime.data);
error = 1;
} else if (!((td->cmp_result == 0 && TEST_true((day == 0 && sec == 0))) ||
(td->cmp_result == -1 && TEST_true((day < 0 || sec < 0))) ||
(td->cmp_result == 1 && TEST_true((day > 0 || sec > 0))))) {
TEST_info("ASN1_TIME_diff(%s) to baseline bad comparison", atime.data);
error = 1;
}
if (!TEST_int_eq(ASN1_TIME_cmp_time_t(&atime, gtime_t), td->cmp_result)) {
TEST_info("ASN1_TIME_cmp_time_t(%s) to baseline bad comparison", atime.data);
error = 1;
}
ptime = ASN1_TIME_set(NULL, td->t);
if (!TEST_ptr(ptime)) {
TEST_info("ASN1_TIME_set(%ld) failed", (long)td->t);
error = 1;
} else {
int local_error = 0;
if (!TEST_int_eq(ASN1_TIME_cmp_time_t(ptime, td->t), 0)) {
TEST_info("ASN1_TIME_set(%ld) compare failed (%s->%s)",
(long)td->t, td->data, ptime->data);
local_error = error = 1;
}
if (!TEST_int_eq(ptime->type, td->expected_type)) {
TEST_info("ASN1_TIME_set(%ld) unexpected type", (long)td->t);
local_error = error = 1;
}
if (local_error)
TEST_info("ASN1_TIME_set() = %*s", ptime->length, ptime->data);
ASN1_TIME_free(ptime);
}
ptime = ASN1_TIME_new();
if (!TEST_ptr(ptime)) {
TEST_info("ASN1_TIME_new() failed");
error = 1;
} else {
int local_error = 0;
if (!TEST_int_eq(ASN1_TIME_set_string(ptime, td->data), td->check_result)) {
TEST_info("ASN1_TIME_set_string_gmt(%s) failed", td->data);
local_error = error = 1;
}
if (!TEST_int_eq(ASN1_TIME_normalize(ptime), td->check_result)) {
TEST_info("ASN1_TIME_normalize(%s) failed", td->data);
local_error = error = 1;
}
if (!TEST_int_eq(ptime->type, td->expected_type)) {
TEST_info("ASN1_TIME_set_string_gmt(%s) unexpected type", td->data);
local_error = error = 1;
}
day = sec = 0;
if (!TEST_true(ASN1_TIME_diff(&day, &sec, ptime, &atime)) || !TEST_int_eq(day, 0) || !TEST_int_eq(sec, 0)) {
TEST_info("ASN1_TIME_diff(day=%d, sec=%d, %s) after ASN1_TIME_set_string_gmt() failed", day, sec, td->data);
local_error = error = 1;
}
if (!TEST_int_eq(ASN1_TIME_cmp_time_t(ptime, gtime_t), td->cmp_result)) {
TEST_info("ASN1_TIME_cmp_time_t(%s) after ASN1_TIME_set_string_gnt() to baseline bad comparison", td->data);
local_error = error = 1;
}
if (local_error)
TEST_info("ASN1_TIME_set_string_gmt() = %*s", ptime->length, ptime->data);
ASN1_TIME_free(ptime);
}
ptime = ASN1_TIME_new();
if (!TEST_ptr(ptime)) {
TEST_info("ASN1_TIME_new() failed");
error = 1;
} else {
int local_error = 0;
if (!TEST_int_eq(ASN1_TIME_set_string(ptime, td->data), td->check_result)) {
TEST_info("ASN1_TIME_set_string(%s) failed", td->data);
local_error = error = 1;
}
day = sec = 0;
if (!TEST_true(ASN1_TIME_diff(&day, &sec, ptime, &atime)) || !TEST_int_eq(day, 0) || !TEST_int_eq(sec, 0)) {
TEST_info("ASN1_TIME_diff(day=%d, sec=%d, %s) after ASN1_TIME_set_string() failed", day, sec, td->data);
local_error = error = 1;
}
if (!TEST_int_eq(ASN1_TIME_cmp_time_t(ptime, gtime_t), td->cmp_result)) {
TEST_info("ASN1_TIME_cmp_time_t(%s) after ASN1_TIME_set_string() to baseline bad comparison", td->data);
local_error = error = 1;
}
if (local_error)
TEST_info("ASN1_TIME_set_string() = %*s", ptime->length, ptime->data);
ASN1_TIME_free(ptime);
}
if (td->type == V_ASN1_UTCTIME) {
ptime = ASN1_TIME_to_generalizedtime(&atime, NULL);
if (td->convert_result == 1 && !TEST_ptr(ptime)) {
TEST_info("ASN1_TIME_to_generalizedtime(%s) failed", atime.data);
error = 1;
} else if (td->convert_result == 0 && !TEST_ptr_null(ptime)) {
TEST_info("ASN1_TIME_to_generalizedtime(%s) should have failed", atime.data);
error = 1;
}
if (ptime != NULL && !TEST_int_eq(ASN1_TIME_cmp_time_t(ptime, td->t), 0)) {
TEST_info("ASN1_TIME_to_generalizedtime(%s->%s) bad result", atime.data, ptime->data);
error = 1;
}
ASN1_TIME_free(ptime);
}
/* else cannot simply convert GENERALIZEDTIME to UTCTIME */
if (error)
TEST_error("atime=%s", atime.data);
return !error;
}
static int test_table_pos(int idx)
{
return test_table(tbl_testdata_pos, idx);
}
static int test_table_neg(int idx)
{
return test_table(tbl_testdata_neg, idx);
}
static int test_table_pos_64bit(int idx)
{
return test_table(tbl_testdata_pos_64bit, idx);
}
static int test_table_neg_64bit(int idx)
{
return test_table(tbl_testdata_neg_64bit, idx);
}
int setup_tests(void)
{
time_t t = -1;
struct tm *ptm = localtime(&t);
ADD_ALL_TESTS(test_table_pos, OSSL_NELEM(tbl_testdata_pos));
if (ptm != NULL) {
TEST_info("Adding negative-sign time_t tests");
ADD_ALL_TESTS(test_table_neg, OSSL_NELEM(tbl_testdata_neg));
}
if (sizeof(time_t) > sizeof(uint32_t)) {
TEST_info("Adding 64-bit time_t tests");
ADD_ALL_TESTS(test_table_pos_64bit, OSSL_NELEM(tbl_testdata_pos_64bit));
if (ptm != NULL) {
TEST_info("Adding negative-sign 64-bit time_t tests");
ADD_ALL_TESTS(test_table_neg_64bit, OSSL_NELEM(tbl_testdata_neg_64bit));
}
}
return 1;
}

View File

@ -432,6 +432,11 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
INCLUDE[mdc2_internal_test]=.. ../include INCLUDE[mdc2_internal_test]=.. ../include
DEPEND[mdc2_internal_test]=../libcrypto libtestutil.a DEPEND[mdc2_internal_test]=../libcrypto libtestutil.a
PROGRAMS_NO_INST=asn1_time_test
SOURCE[asn1_time_test]=asn1_time_test.c
INCLUDE[asn1_time_test]=.. ../include
DEPEND[asn1_time_test]=../libcrypto libtestutil.a
# We disable this test completely in a shared build because it deliberately # We disable this test completely in a shared build because it deliberately
# redefines some internal libssl symbols. This doesn't work in a non-shared # redefines some internal libssl symbols. This doesn't work in a non-shared
# build # build

View File

@ -0,0 +1,12 @@
#! /usr/bin/env perl
# Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
use OpenSSL::Test::Simple;
simple_test("test_asn1_time", "asn1_time_test");

View File

@ -96,10 +96,7 @@ static int test_offset(int idx)
return 0; return 0;
} }
if (at.type == V_ASN1_UTCTIME) ret = ASN1_TIME_cmp_time_t(&at, the_time);
ret = ASN1_UTCTIME_cmp_time_t(&at, the_time);
else
return 1; /* no other cmp_time_t() functions available, yet */
if (!TEST_int_eq(testdata->time_result, ret)) { if (!TEST_int_eq(testdata->time_result, ret)) {
TEST_info("ASN1_UTCTIME_cmp_time_t() test failed for %s\n", at.data); TEST_info("ASN1_UTCTIME_cmp_time_t() test failed for %s\n", at.data);

View File

@ -4376,3 +4376,6 @@ RAND_DRBG_get0_global 4319 1_1_1 EXIST::FUNCTION:
RAND_priv_bytes 4320 1_1_1 EXIST::FUNCTION: RAND_priv_bytes 4320 1_1_1 EXIST::FUNCTION:
BN_priv_rand 4321 1_1_1 EXIST::FUNCTION: BN_priv_rand 4321 1_1_1 EXIST::FUNCTION:
BN_priv_rand_range 4322 1_1_1 EXIST::FUNCTION: BN_priv_rand_range 4322 1_1_1 EXIST::FUNCTION:
ASN1_TIME_normalize 4323 1_1_1 EXIST::FUNCTION:
ASN1_TIME_cmp_time_t 4324 1_1_1 EXIST::FUNCTION:
ASN1_TIME_compare 4325 1_1_1 EXIST::FUNCTION: