diff options
Diffstat (limited to 'trust')
-rw-r--r-- | trust/builder.c | 100 | ||||
-rw-r--r-- | trust/tests/test-builder.c | 14 |
2 files changed, 81 insertions, 33 deletions
diff --git a/trust/builder.c b/trust/builder.c index e41d73f..15999bb 100644 --- a/trust/builder.c +++ b/trust/builder.c @@ -227,16 +227,72 @@ calc_check_value (const unsigned char *data, memcpy (check_value, checksum, 3); } +static int +atoin (const char *p, + int digits) +{ + int ret = 0, base = 1; + while(--digits >= 0) { + if (p[digits] < '0' || p[digits] > '9') + return -1; + ret += (p[digits] - '0') * base; + base *= 10; + } + return ret; +} + +static int +century_for_two_digit_year (int year) +{ + time_t now; + struct tm tm; + int century, current; + + return_val_if_fail (year >= 0 && year <= 99, -1); + + /* Get the current year */ + now = time (NULL); + return_val_if_fail (now >= 0, -1); + if (!gmtime_r (&now, &tm)) + return_val_if_reached (-1); + + current = (tm.tm_year % 100); + century = (tm.tm_year + 1900) - current; + + /* + * Check if it's within 40 years before the + * current date. + */ + if (current < 40) { + if (year < current) + return century; + if (year > 100 - (40 - current)) + return century - 100; + } else { + if (year < current && year > (current - 40)) + return century; + } + + /* + * If it's after then adjust for overflows to + * the next century. + */ + if (year < current) + return century + 100; + else + return century; +} + static bool calc_date (node_asn *node, const char *field, CK_DATE *date) { node_asn *choice; - struct tm when; char buf[64]; - time_t timet; + int century; char *sub; + int year; int len; int ret; @@ -252,39 +308,43 @@ calc_date (node_asn *node, sub = strconcat (field, ".", buf, NULL); + /* + * So here we take a shortcut and just copy the date from the + * certificate into the CK_DATE. This doesn't take into account + * time zones. However the PKCS#11 spec does not say what timezone + * the dates are in. In the PKCS#11 value have a day resolution, + * and time zones aren't that critical. + */ + if (strcmp (buf, "generalTime") == 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_general (buf, &when); + return_val_if_fail (len >= 8, false); + + /* Same as first 8 characters of date */ + memcpy (date, buf, 8); } 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); + return_val_if_fail (len >= 6, false); + + year = atoin (buf, 2); + return_val_if_fail (year > 0, false); + + century = century_for_two_digit_year (year); + return_val_if_fail (century >= 0, false); + + snprintf ((char *)date->year, 3, "%02d", century); + memcpy (((char *)date) + 2, buf, 6); } else { return_val_if_reached (false); } free (sub); - - if (timet < 0) - return false; - - assert (sizeof (date->year) == 4); - snprintf ((char *)buf, 5, "%04d", 1900 + when.tm_year); - memcpy (date->year, buf, 4); - - assert (sizeof (date->month) == 2); - snprintf ((char *)buf, 3, "%02d", when.tm_mon + 1); - memcpy (date->month, buf, 2); - - assert (sizeof (date->day) == 2); - snprintf ((char *)buf, 3, "%02d", when.tm_mday); - memcpy (date->day, buf, 2); - return true; } diff --git a/trust/tests/test-builder.c b/trust/tests/test-builder.c index 7cab1f6..a875b96 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); |