From aa39ce54f3768272847160bb52d1e96b974b2d2f Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 29 Mar 2013 13:17:29 +0100 Subject: [PATCH] Don't respect timezones on 32-bit systems for dates later than 2038 A previous patch changed the processing for dates where on 32-bit systems CKA_START_DATE or CKA_END_DATE later than 2038 would just be blank (since they're optional). But we can do better. The only reason we need to convert to time_t is to add in timezone offsets. Most dates in certificates don't have timezone offsets anyway, and failing to add them in doesn't make such a big difference because: CKA_START_DATE and CKA_END_DATE don't have time components, and are at day resolution. Sure the timezone offset can make them change to a different day. But since these optional, low resolution fields aren't very usable anyway, we don't have to worry if we can't roll in the time zone offset. In fact the PKCS#11 spec does not say whether these dates are in UTC TZ. So fudging a little on 32-bit systems isn't the end of the world. https://bugs.freedesktop.org/show_bug.cgi?id=62825 --- common/asn1.c | 92 ++++++++++++++++++++++------------------------ common/asn1.h | 4 +- trust/builder.c | 8 ++-- trust/tests/test-builder.c | 14 +------ 4 files changed, 51 insertions(+), 67 deletions(-) diff --git a/common/asn1.c b/common/asn1.c index c98d959..7d3a850 100644 --- a/common/asn1.c +++ b/common/asn1.c @@ -248,7 +248,7 @@ two_to_four_digit_year (int year) return century + year; } -static int +static bool parse_utc_time (const char *time, size_t n_time, struct tm *when, @@ -263,7 +263,7 @@ parse_utc_time (const char *time, /* YYMMDDhhmmss.ffff Z | +0000 */ if (n_time < 6 || n_time >= 28) - return 0; + return false; /* Reset everything to default legal values */ memset (when, 0, sizeof (*when)); @@ -311,11 +311,11 @@ parse_utc_time (const char *time, when->tm_hour < 0 || when->tm_hour > 23 || when->tm_min < 0 || when->tm_min > 59 || when->tm_sec < 0 || when->tm_sec > 59) - return 0; + return false; /* Make sure all that got parsed */ if (p != e) - return 0; + return false; /* Now the remaining optional stuff */ e = time + n_time; @@ -337,7 +337,7 @@ parse_utc_time (const char *time, off = atoin (p, 2) * 3600; if (off < 0 || off > 86400) - return 0; + return false; p += 2; if (p + 2 <= e) { @@ -354,12 +354,12 @@ parse_utc_time (const char *time, /* Make sure everything got parsed */ if (p != e) - return 0; + return false; - return 1; + return true; } -static int +static bool parse_general_time (const char *time, size_t n_time, struct tm *when, @@ -373,7 +373,7 @@ parse_general_time (const char *time, /* YYYYMMDDhhmmss.ffff Z | +0000 */ if (n_time < 8 || n_time >= 30) - return 0; + return false; /* Reset everything to default legal values */ memset (when, 0, sizeof (*when)); @@ -415,11 +415,11 @@ parse_general_time (const char *time, when->tm_hour < 0 || when->tm_hour > 23 || when->tm_min < 0 || when->tm_min > 59 || when->tm_sec < 0 || when->tm_sec > 59) - return 0; + return false; /* Make sure all that got parsed */ if (p != e) - return 0; + return false; /* Now the remaining optional stuff */ e = time + n_time; @@ -441,7 +441,7 @@ parse_general_time (const char *time, off = atoin (p, 2) * 3600; if (off < 0 || off > 86400) - return 0; + return false; p += 2; if (p + 2 <= e) { @@ -458,70 +458,66 @@ parse_general_time (const char *time, /* Make sure everything got parsed */ if (p != e) - return 0; + return false; - return 1; + return true; } -static time_t -when_and_offset_to_time_t (struct tm *when, - int tz_offset) +static void +add_offset_to_tm (struct tm *when, + int tz_offset) { time_t timet; - /* A 32-bit time, cannot represent this time */ - if (sizeof (time_t) <= 4 && when->tm_year >= 138) { - return -1; + /* + * A 32-bit time, cannot represent this time later + * than the year 2038. So we just skip adding the + * timezone offset. The best we can do. + */ + if (sizeof (time_t) <= 4 && when->tm_year >= 138) + return; /* Convert to seconds since epoch */ - } else { - timet = timegm (when); - return_val_if_fail (timet >= 0, -1); - timet += tz_offset; - } + timet = timegm (when); + return_if_fail (timet >= 0); + timet += tz_offset; if (!gmtime_r (&timet, when)) - return_val_if_reached (-1); - - return timet; + return_if_reached (); } -time_t +bool p11_asn1_parse_utc (const char *time_str, struct tm *when) { - struct tm dummy; int tz_offset; - int ret; - if (!when) - when = &dummy; + return_val_if_fail (time_str != NULL, false); + return_val_if_fail (when != NULL, false); - ret = parse_utc_time (time_str, strlen (time_str), - when, &tz_offset); - if (!ret) - return -1; + if (!parse_utc_time (time_str, strlen (time_str), + when, &tz_offset)) + return false; - return when_and_offset_to_time_t (when, tz_offset); + add_offset_to_tm (when, tz_offset); + return true; } -time_t +bool p11_asn1_parse_general (const char *time_str, struct tm *when) { - struct tm dummy; int tz_offset; - int ret; - if (!when) - when = &dummy; + return_val_if_fail (time_str != NULL, false); + return_val_if_fail (when != NULL, false); - ret = parse_general_time (time_str, strlen (time_str), - when, &tz_offset); - if (!ret) - return -1; + if (!parse_general_time (time_str, strlen (time_str), + when, &tz_offset)) + return false; - return when_and_offset_to_time_t (when, tz_offset); + add_offset_to_tm (when, tz_offset); + return true; } ssize_t diff --git a/common/asn1.h b/common/asn1.h index c79e8f6..209e81f 100644 --- a/common/asn1.h +++ b/common/asn1.h @@ -55,10 +55,10 @@ node_asn * p11_asn1_create (p11_dict *asn1_defs, unsigned char * p11_asn1_encode (node_asn *asn, size_t *der_len); -time_t p11_asn1_parse_utc (const char *time_str, +bool p11_asn1_parse_utc (const char *time_str, struct tm *when); -time_t p11_asn1_parse_general (const char *time_str, +bool p11_asn1_parse_general (const char *time_str, struct tm *when); ssize_t p11_asn1_tlv_length (const unsigned char *data, diff --git a/trust/builder.c b/trust/builder.c index 32f2d1b..b1ed706 100644 --- a/trust/builder.c +++ b/trust/builder.c @@ -235,7 +235,7 @@ calc_date (node_asn *node, node_asn *choice; struct tm when; char buf[64]; - time_t timet; + bool parsed; char *sub; int len; int ret; @@ -256,13 +256,13 @@ calc_date (node_asn *node, len = sizeof (buf) - 1; ret = asn1_read_value (node, sub, buf, &len); return_val_if_fail (ret == ASN1_SUCCESS, false); - timet = p11_asn1_parse_general (buf, &when); + parsed = p11_asn1_parse_general (buf, &when); } else if (strcmp (buf, "utcTime") == 0) { len = sizeof (buf) - 1; ret = asn1_read_value (node, sub, buf, &len); return_val_if_fail (ret == ASN1_SUCCESS, false); - timet = p11_asn1_parse_utc (buf, &when); + parsed = p11_asn1_parse_utc (buf, &when); } else { return_val_if_reached (false); @@ -270,7 +270,7 @@ calc_date (node_asn *node, free (sub); - if (timet < 0) + if (!parsed) return false; assert (sizeof (date->year) == 4); diff --git a/trust/tests/test-builder.c b/trust/tests/test-builder.c index 5ce3b22..7ae3f14 100644 --- a/trust/tests/test-builder.c +++ b/trust/tests/test-builder.c @@ -552,7 +552,7 @@ test_build_distant_end_date (CuTest *cu) }; CK_ATTRIBUTE expected[] = { - { CKA_END_DATE, }, + { CKA_END_DATE, "20671229", 8 }, { CKA_START_DATE, "20130327", 8 }, { CKA_INVALID }, }; @@ -562,18 +562,6 @@ test_build_distant_end_date (CuTest *cu) setup (cu); - /* - * On a 32-bit system, the end date will be too big to compute with - * libc. So it'll be empty, since this is an optional field. - */ - if (sizeof (time_t) <= 4) { - expected[0].pValue = ""; - expected[0].ulValueLen = 0; - } else { - expected[0].pValue = "20671229"; - expected[0].ulValueLen = 8; - } - attrs = NULL; rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input)); CuAssertIntEquals (cu, CKR_OK, rv); -- 1.8.1.4