diff --git a/security/pkix/test/gtest/pkixder_universal_types_tests.cpp b/security/pkix/test/gtest/pkixder_universal_types_tests.cpp index 9a5f9335accc..2ce9cdd795fe 100644 --- a/security/pkix/test/gtest/pkixder_universal_types_tests.cpp +++ b/security/pkix/test/gtest/pkixder_universal_types_tests.cpp @@ -305,13 +305,34 @@ TEST_F(pkixder_universal_types_tests, EnumeratedInvalidZeroLength) 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' }; @@ -328,27 +349,24 @@ TEST_F(pkixder_universal_types_tests, GeneralizedTimeOffset) 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; @@ -361,6 +379,354 @@ TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidZeroLength) 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) {