Add tests for TIME functions that accept offsets

To consciously change them in the future without accidental breakage.

Change-Id: Id5d073f8781e63cbf6dbb20cc2615e6655b28222
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/75129
Reviewed-by: David Benjamin <davidben@google.com>
Auto-Submit: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc
index 7ac9d0e..c54ed29 100644
--- a/crypto/asn1/asn1_test.cc
+++ b/crypto/asn1/asn1_test.cc
@@ -1159,6 +1159,51 @@
   EXPECT_FALSE(ASN1_TIME_set_string_X509(nullptr, "19700101000000-0400"));
 }
 
+TEST(ASN1Test, UTCTimeZoneOffsets) {
+  bssl::UniquePtr<ASN1_STRING> s(ASN1_STRING_new());
+  ASSERT_TRUE(s);
+
+  ASSERT_TRUE(ASN1_UTCTIME_set_string(s.get(), "700101000000Z"));
+  EXPECT_EQ(V_ASN1_UTCTIME, ASN1_STRING_type(s.get()));
+  EXPECT_EQ("700101000000Z", ASN1StringToStdString(s.get()));
+
+  // UTCTIME_set_string should not allow a timezeone offset
+  EXPECT_FALSE(ASN1_UTCTIME_set_string(s.get(), "700101000000-0400"));
+
+  // Forcibly construct a utc time with a timezone offset.
+  ASSERT_TRUE(ASN1_STRING_set(s.get(), "700101000000-0400",
+                              strlen("700101000000-0400")));
+  EXPECT_EQ(V_ASN1_UTCTIME, ASN1_STRING_type(s.get()));
+  EXPECT_EQ("700101000000-0400", ASN1StringToStdString(s.get()));
+
+  // check is expected to be valid with timezeone offsets
+  ASSERT_TRUE(ASN1_UTCTIME_check(s.get()));
+
+  // cmp_time_t allows timezeone offset, and we are expected to be 4 hours
+  // behind the epoch.
+  EXPECT_EQ(ASN1_UTCTIME_cmp_time_t(s.get(), (4 * 60 * 60 * -1)), 0);
+
+  // Conscrypt expects a utc time with an arbitrary offset to be
+  // accepted by ASN1_TIME_to_generalizedtime.
+  bssl::UniquePtr<ASN1_STRING> g(
+      ASN1_TIME_to_generalizedtime(s.get(), nullptr));
+  ASSERT_TRUE(g);
+  EXPECT_EQ(V_ASN1_GENERALIZEDTIME, ASN1_STRING_type(g.get()));
+  // crbug.com/389147378
+  // This should be the correct value
+  // EXPECT_EQ("19691231200000Z", ASN1StringToStdString(g.get()));
+  // But this function currently generates invalid times.
+  EXPECT_EQ("19700101000000-0400", ASN1StringToStdString(g.get()));
+  // Force this to be a generalized time the same as our utc time
+  EXPECT_TRUE(ASN1_GENERALIZEDTIME_set_string(g.get(), "19691231200000Z"));
+
+  // ASN1_TIME_diff is expected to accept timezone offsets
+  int days, secs;
+  EXPECT_TRUE(ASN1_TIME_diff(&days, &secs, s.get(), g.get()));
+  EXPECT_EQ(days, 0);
+  EXPECT_EQ(secs, 0);
+}
+
 TEST(ASN1Test, AdjTime) {
   struct tm tm1, tm2;
   int days, secs;