Bug 998513 - Test GeneralizedTime encodings in mozilla::pkix. r=keeler.
authorCamilo Viecco <cviecco@mozilla.com>
Fri, 13 Jun 2014 12:50:11 -0700
changeset 188614 dec106a20917ae66d25193f1fb99059c49ddf31a
parent 188613 c1ceb0b9da949e2a8a088152682102602dcafdae
child 188615 a6cf083123ebb26a977801bf31554e0a661d980d
push id44880
push usercviecco@mozilla.com
push dateFri, 13 Jun 2014 20:57:38 +0000
treeherdermozilla-inbound@dec106a20917 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs998513
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 998513 - Test GeneralizedTime encodings in mozilla::pkix. r=keeler.
security/pkix/test/gtest/pkixder_universal_types_tests.cpp
--- a/security/pkix/test/gtest/pkixder_universal_types_tests.cpp
+++ b/security/pkix/test/gtest/pkixder_universal_types_tests.cpp
@@ -300,72 +300,438 @@ TEST_F(pkixder_universal_types_tests, En
   ASSERT_EQ(Success, input.Init(DER_ENUMERATED_INVALID_ZERO_LENGTH,
                                 sizeof DER_ENUMERATED_INVALID_ZERO_LENGTH));
 
   uint8_t value = 0;
   ASSERT_EQ(Failure, Enumerated(input, value));
   ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
 }
 
-// TODO: Test all acceptable timestamp formats. Find out what formats
-// are being used by looking at large collection of certs.
+////////////////////////////////////////
+// GeneralizedTime
+//
+// From RFC 5280 section 4.1.2.5.2
+//
+//   For the purposes of this profile, GeneralizedTime values MUST be
+//   expressed in Greenwich Mean Time (Zulu) and MUST include seconds
+//   (i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds
+//   is zero.  GeneralizedTime values MUST NOT include fractional seconds.
+//
+// And from from RFC 6960 (OCSP) section 4.2.2.1:
+//
+//   Responses can contain four times -- thisUpdate, nextUpdate,
+//   producedAt, and revocationTime.  The semantics of these fields are
+//   defined in Section 2.4.  The format for GeneralizedTime is as
+//   specified in Section 4.1.2.5.2 of [RFC5280].
+//
+// So while we can could accept other ASN1 (ITU-T X.680) encodings for
+// GeneralizedTime we should not accept them, and breaking reading of these
+// other encodings is actually encouraged.
+
+// TODO(Bug 1023605) a GeneralizedTimes with a timezone offset are should not
+// be considered valid
 TEST_F(pkixder_universal_types_tests, GeneralizedTimeOffset)
 {
   const uint8_t DER_GENERALIZED_TIME_OFFSET[] = {
-    0x18,
-    19,
+    0x18,                           // Generalized Time
+    19,                             // Length = 19
     '1', '9', '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', '-',
     '0', '7', '0', '0'
   };
 
   Input input;
   ASSERT_EQ(Success, input.Init(DER_GENERALIZED_TIME_OFFSET,
                                 sizeof DER_GENERALIZED_TIME_OFFSET));
 
   PRTime value = 0;
   ASSERT_EQ(Success, GeneralizedTime(input, value));
   ASSERT_EQ(673573540000000, value);
 }
 
 TEST_F(pkixder_universal_types_tests, GeneralizedTimeGMT)
 {
   const uint8_t DER_GENERALIZED_TIME_GMT[] = {
-    0x18,
-    15,
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
     '1', '9', '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'
   };
 
   Input input;
-  Result rv1 = input.Init(DER_GENERALIZED_TIME_GMT,
-                          sizeof DER_GENERALIZED_TIME_GMT);
-  ASSERT_EQ(Success, rv1);
-
+  ASSERT_EQ(Success, input.Init(DER_GENERALIZED_TIME_GMT,
+                                sizeof DER_GENERALIZED_TIME_GMT));
   PRTime value = 0;
-  Result rv2 = GeneralizedTime(input, value);
-  ASSERT_EQ(Success, rv2);
+  ASSERT_EQ(Success, GeneralizedTime(input, value));
   ASSERT_EQ(673548340000000, value);
 }
 
 TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidZeroLength)
 {
   const uint8_t DER_GENERALIZED_TIME_INVALID_ZERO_LENGTH[] = {
-    0x18,
-    0x00
+    0x18,                           // GeneralizedTime
+    0x00                            // Length = 0
   };
 
   Input input;
   ASSERT_EQ(Success,
             input.Init(DER_GENERALIZED_TIME_INVALID_ZERO_LENGTH,
                        sizeof DER_GENERALIZED_TIME_INVALID_ZERO_LENGTH));
 
   PRTime value = 0;
   ASSERT_EQ(Failure, GeneralizedTime(input, value));
   ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
 }
 
+// A non zulu time should fail
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidLocal)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_LOCAL[] = {
+    0x18,                           // Generalized Time
+    14,                             // Length = 14
+    '1', '9', '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0'
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_LOCAL,
+                       sizeof DER_GENERALIZED_TIME_INVALID_LOCAL));
+
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+// A time missing seconds and zulu should fail
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidTruncated)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_TRUNCATED[] = {
+    0x18,                           // Generalized Time
+    12,                             // Length = 12
+    '1', '9', '9', '1', '0', '5', '0', '6', '1', '6', '4', '5'
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_TRUNCATED,
+                       sizeof DER_GENERALIZED_TIME_INVALID_TRUNCATED));
+
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+// TODO(bug 1023605) Generalized Times without seconds should not be
+// considered valid
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeNoSeconds)
+{
+  const uint8_t DER_GENERALIZED_TIME_NO_SECONDS[] = {
+    0x18,                           // Generalized Time
+    13,                             // Length = 13
+    '1', '9', '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', 'Z'
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_NO_SECONDS,
+                       sizeof DER_GENERALIZED_TIME_NO_SECONDS));
+  PRTime value = 0;
+  ASSERT_EQ(Success, GeneralizedTime(input, value));
+  ASSERT_EQ(673548300000000, value);
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidPrefixedYear)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_PREFIXED_YEAR[] = {
+    0x18,                           // Generalized Time
+    16,                             // Length = 16
+    ' ', '1', '9', '9', '1', '0', '1', '0', '1', '0', '1', '0', '1', '0', '1', 'Z'
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_PREFIXED_YEAR,
+                       sizeof DER_GENERALIZED_TIME_INVALID_PREFIXED_YEAR));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalid5DigitYear)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_5_DIGIT_YEAR[] = {
+    0x18,                           // Generalized Time
+    16,                             // Length = 16
+    '1', '1', '1', '1', '1', '0', '1', '0', '1', '0', '1', '0', '1', '0', '1', 'Z'
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_5_DIGIT_YEAR,
+                       sizeof DER_GENERALIZED_TIME_INVALID_5_DIGIT_YEAR));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidMonth)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_MONTH[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '1', '9', '9', '1', //YYYY (1991)
+    '1', '3', //MM 13th month of the year
+    '0', '6', '1', '6', '4', '5', '4', '0', 'Z'
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_MONTH,
+                       sizeof DER_GENERALIZED_TIME_INVALID_MONTH));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+// TODO(bug 1023437) Generalized times with invalid days for a given month
+// should be rejected
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidDayFeb)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_DAY_FEB[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '1', '9', '9', '1', // YYYY 1991
+    '0', '2', // MM (February)
+    '3', '0', // DD (the 30th which does not exist)
+    '1', '6', '4', '5', '4', '0', 'Z'
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_DAY_FEB,
+                       sizeof DER_GENERALIZED_TIME_INVALID_DAY_FEB));
+  PRTime value = 0;
+  ASSERT_EQ(Success, GeneralizedTime(input, value));
+  // The current invalid returned value is Sat, 02 Mar 1991 16:45:40 GMT
+  ASSERT_EQ(667932340000000, value);
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidDayDec)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_DAY_DEC[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '1', '9', '9', '1', // YYYY 1991
+    '1', '2', // MM (December)
+    '3', '2', // DD (the 32nd which does not exist)
+    '1', '6', '4', '5', '4', '0', 'Z'
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_DAY_DEC,
+                       sizeof DER_GENERALIZED_TIME_INVALID_DAY_DEC));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeLeapSecondJune)
+{
+  // No leap seconds ever (allowing them would be non-trivial).
+  const uint8_t DER_GENERALIZED_TIME_LEAP_SECOND_JUNE[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30)
+    '2', '3', '5', '9', '6', '0', 'Z' // HHMMSSZ (23:59:60 Zulu)
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_LEAP_SECOND_JUNE,
+                       sizeof DER_GENERALIZED_TIME_LEAP_SECOND_JUNE));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidHours)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_HOURS[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30)
+    '2', '5', '5', '9', '0', '1', 'Z' // HHMMSSZ (!!25!!:59:01 Zulu)
+  };
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_HOURS,
+                       sizeof DER_GENERALIZED_TIME_INVALID_HOURS));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidMinutes)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_MINUTES[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30)
+    '2', '3', '6', '0', '5', '9', 'Z' // HHMMSSZ (23:!!!60!!!:01 Zulu)
+  };
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_MINUTES,
+                       sizeof DER_GENERALIZED_TIME_INVALID_MINUTES));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidSeconds)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_SECONDS[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30)
+    '2', '3', '5', '9', '6', '1', 'Z' // HHMMSSZ (23:59:!!!!61!!!! Zulu)
+  };
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_SECONDS,
+                       sizeof DER_GENERALIZED_TIME_INVALID_SECONDS));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidZulu)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_ZULU[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30)
+    '2', '3', '5', '9', '5', '9', 'z' // HHMMSSZ (23:59:59 !!!z!!!) should be Z
+  };
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_ZULU,
+                       sizeof DER_GENERALIZED_TIME_INVALID_ZULU));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidExtraData)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_EXTRA_DATA[] = {
+    0x18,                           // Generalized Time
+    16,                             // Length = 16
+    '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30)
+    '2', '3', '5', '9', '5', '9', 'Z', // HHMMSSZ (23:59:59Z)
+    0 // Extra null character
+  };
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_EXTRA_DATA,
+                       sizeof DER_GENERALIZED_TIME_INVALID_EXTRA_DATA));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidCenturyChar)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_CENTURY_CHAR[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    'X', '9', '9', '1', '1', '2', '0', '6', // YYYYMMDD (X991-12-06)
+    '1', '6', '4', '5', '4', '0', 'Z' // HHMMSSZ (16:45:40Z)
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_CENTURY_CHAR,
+                       sizeof DER_GENERALIZED_TIME_INVALID_CENTURY_CHAR));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidYearChar)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_YEAR_CHAR[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '1', '9', '9', 'I', '0', '1', '0', '6', // YYYYMMDD (199I-12-06)
+    '1', '6', '4', '5', '4', '0', 'Z' // HHMMSSZ (16:45:40Z)
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_YEAR_CHAR,
+                       sizeof DER_GENERALIZED_TIME_INVALID_YEAR_CHAR));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidMonthChar)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_MONTH_CHAR[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '1', '9', '9', '1', '0', 'I', '0', '6', // YYYYMMDD (1991-0I-06)
+    '1', '6', '4', '5', '4', '0', 'Z' // HHMMSSZ (16:45:40Z)
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_MONTH_CHAR,
+                       sizeof DER_GENERALIZED_TIME_INVALID_MONTH_CHAR));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidDayChar)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_DAY_CHAR[] = {
+    0x18,                           // Generalized Time
+    15,                             // Length = 15
+    '1', '9', '9', '1', '0', '1', '0', 'S', // YYYYMMDD (1991-01-0S)
+    '1', '6', '4', '5', '4', '0', 'Z' // HHMMSSZ (16:45:40Z)
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_DAY_CHAR,
+                       sizeof DER_GENERALIZED_TIME_INVALID_DAY_CHAR));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
+TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidFractionalSeconds)
+{
+  const uint8_t DER_GENERALIZED_TIME_INVALID_FRACTIONAL_SECONDS[] = {
+    0x18,                           // Generalized Time
+    17,                             // Length = 17
+    '1', '9', '9', '1', '0', '1', '0', '1', // YYYYMMDD (1991-01-01)
+    '1', '6', '4', '5', '4', '0', '.', '3', 'Z' // HHMMSS.FFF (16:45:40.3Z)
+  };
+
+  Input input;
+  ASSERT_EQ(Success,
+            input.Init(DER_GENERALIZED_TIME_INVALID_FRACTIONAL_SECONDS,
+                       sizeof DER_GENERALIZED_TIME_INVALID_FRACTIONAL_SECONDS));
+  PRTime value = 0;
+  ASSERT_EQ(Failure, GeneralizedTime(input, value));
+  ASSERT_EQ(SEC_ERROR_INVALID_TIME, PR_GetError());
+}
+
 TEST_F(pkixder_universal_types_tests, Integer_0_127)
 {
   for (uint8_t i = 0; i <= 127; ++i) {
     const uint8_t DER[] = {
       0x02, // INTEGER
       0x01, // length
       i,    // value
     };