| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
| /* This code is made available to you under your choice of the following sets |
| * of licensing terms: |
| */ |
| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| */ |
| /* Copyright 2013 Mozilla Contributors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <limits> |
| #include <stdint.h> |
| #include <vector> |
| |
| #include "pkixgtest.h" |
| |
| #include "mozpkix/pkixder.h" |
| |
| using namespace mozilla::pkix; |
| using namespace mozilla::pkix::der; |
| using namespace mozilla::pkix::test; |
| using namespace std; |
| |
| class pkixder_universal_types_tests : public ::testing::Test { }; |
| |
| TEST_F(pkixder_universal_types_tests, BooleanTrue01) |
| { |
| const uint8_t DER_BOOLEAN_TRUE_01[] = { |
| 0x01, // BOOLEAN |
| 0x01, // length |
| 0x01 // invalid |
| }; |
| Input input(DER_BOOLEAN_TRUE_01); |
| Reader reader(input); |
| bool value = false; |
| ASSERT_EQ(Result::ERROR_BAD_DER, Boolean(reader, value)); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, BooleanTrue42) |
| { |
| const uint8_t DER_BOOLEAN_TRUE_42[] = { |
| 0x01, // BOOLEAN |
| 0x01, // length |
| 0x42 // invalid |
| }; |
| Input input(DER_BOOLEAN_TRUE_42); |
| Reader reader(input); |
| bool value = false; |
| ASSERT_EQ(Result::ERROR_BAD_DER, Boolean(reader, value)); |
| } |
| |
| static const uint8_t DER_BOOLEAN_TRUE[] = { |
| 0x01, // BOOLEAN |
| 0x01, // length |
| 0xff // true |
| }; |
| |
| TEST_F(pkixder_universal_types_tests, BooleanTrueFF) |
| { |
| Input input(DER_BOOLEAN_TRUE); |
| Reader reader(input); |
| bool value = false; |
| ASSERT_EQ(Success, Boolean(reader, value)); |
| ASSERT_TRUE(value); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, BooleanFalse) |
| { |
| const uint8_t DER_BOOLEAN_FALSE[] = { |
| 0x01, // BOOLEAN |
| 0x01, // length |
| 0x00 // false |
| }; |
| Input input(DER_BOOLEAN_FALSE); |
| Reader reader(input); |
| |
| bool value = true; |
| ASSERT_EQ(Success, Boolean(reader, value)); |
| ASSERT_FALSE(value); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, BooleanInvalidLength) |
| { |
| const uint8_t DER_BOOLEAN_INVALID_LENGTH[] = { |
| 0x01, // BOOLEAN |
| 0x02, // length |
| 0x42, 0x42 // invalid |
| }; |
| Input input(DER_BOOLEAN_INVALID_LENGTH); |
| Reader reader(input); |
| |
| bool value = true; |
| ASSERT_EQ(Result::ERROR_BAD_DER, Boolean(reader, value)); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, BooleanInvalidZeroLength) |
| { |
| const uint8_t DER_BOOLEAN_INVALID_ZERO_LENGTH[] = { |
| 0x01, // BOOLEAN |
| 0x00 // length |
| }; |
| Input input(DER_BOOLEAN_INVALID_ZERO_LENGTH); |
| Reader reader(input); |
| |
| bool value = true; |
| ASSERT_EQ(Result::ERROR_BAD_DER, Boolean(reader, value)); |
| } |
| |
| // OptionalBoolean implements decoding of OPTIONAL BOOLEAN DEFAULT FALSE. |
| // If the field is present, it must be a valid encoding of a BOOLEAN with |
| // value TRUE. If the field is not present, it defaults to FALSE. For |
| // compatibility reasons, OptionalBoolean also accepts encodings where the field |
| // is present with value FALSE (this is technically not a valid DER encoding). |
| TEST_F(pkixder_universal_types_tests, OptionalBooleanValidEncodings) |
| { |
| { |
| const uint8_t DER_OPTIONAL_BOOLEAN_PRESENT_TRUE[] = { |
| 0x01, // BOOLEAN |
| 0x01, // length |
| 0xff // true |
| }; |
| Input input(DER_OPTIONAL_BOOLEAN_PRESENT_TRUE); |
| Reader reader(input); |
| bool value = false; |
| ASSERT_EQ(Success, OptionalBoolean(reader, value)) << |
| "Should accept the only valid encoding of a present OPTIONAL BOOLEAN"; |
| ASSERT_TRUE(value); |
| ASSERT_TRUE(reader.AtEnd()); |
| } |
| |
| { |
| // The OPTIONAL BOOLEAN is omitted in this data. |
| const uint8_t DER_INTEGER_05[] = { |
| 0x02, // INTEGER |
| 0x01, // length |
| 0x05 |
| }; |
| Input input(DER_INTEGER_05); |
| Reader reader(input); |
| bool value = true; |
| ASSERT_EQ(Success, OptionalBoolean(reader, value)) << |
| "Should accept a valid encoding of an omitted OPTIONAL BOOLEAN"; |
| ASSERT_FALSE(value); |
| ASSERT_FALSE(reader.AtEnd()); |
| } |
| |
| { |
| Input input; |
| ASSERT_EQ(Success, input.Init(reinterpret_cast<const uint8_t*>(""), 0)); |
| Reader reader(input); |
| bool value = true; |
| ASSERT_EQ(Success, OptionalBoolean(reader, value)) << |
| "Should accept another valid encoding of an omitted OPTIONAL BOOLEAN"; |
| ASSERT_FALSE(value); |
| ASSERT_TRUE(reader.AtEnd()); |
| } |
| } |
| |
| TEST_F(pkixder_universal_types_tests, OptionalBooleanInvalidEncodings) |
| { |
| const uint8_t DER_OPTIONAL_BOOLEAN_PRESENT_FALSE[] = { |
| 0x01, // BOOLEAN |
| 0x01, // length |
| 0x00 // false |
| }; |
| |
| { |
| Input input(DER_OPTIONAL_BOOLEAN_PRESENT_FALSE); |
| Reader reader(input); |
| bool value = true; |
| ASSERT_EQ(Success, OptionalBoolean(reader, value)) << |
| "Should accept an invalid, default-value encoding of OPTIONAL BOOLEAN"; |
| ASSERT_FALSE(value); |
| ASSERT_TRUE(reader.AtEnd()); |
| } |
| |
| const uint8_t DER_OPTIONAL_BOOLEAN_PRESENT_42[] = { |
| 0x01, // BOOLEAN |
| 0x01, // length |
| 0x42 // (invalid value for a BOOLEAN) |
| }; |
| |
| { |
| Input input(DER_OPTIONAL_BOOLEAN_PRESENT_42); |
| Reader reader(input); |
| bool value; |
| ASSERT_EQ(Result::ERROR_BAD_DER, OptionalBoolean(reader, value)) << |
| "Should reject an invalid-valued encoding of OPTIONAL BOOLEAN"; |
| } |
| } |
| |
| TEST_F(pkixder_universal_types_tests, Enumerated) |
| { |
| const uint8_t DER_ENUMERATED[] = { |
| 0x0a, // ENUMERATED |
| 0x01, // length |
| 0x42 // value |
| }; |
| Input input(DER_ENUMERATED); |
| Reader reader(input); |
| |
| uint8_t value = 0; |
| ASSERT_EQ(Success, Enumerated(reader, value)); |
| ASSERT_EQ(0x42, value); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, EnumeratedNotShortestPossibleDER) |
| { |
| const uint8_t DER_ENUMERATED[] = { |
| 0x0a, // ENUMERATED |
| 0x02, // length |
| 0x00, 0x01 // value |
| }; |
| Input input(DER_ENUMERATED); |
| Reader reader(input); |
| |
| uint8_t value = 0; |
| ASSERT_EQ(Result::ERROR_INVALID_INTEGER_ENCODING, Enumerated(reader, value)); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, EnumeratedOutOfAcceptedRange) |
| { |
| // Although this is a valid ENUMERATED value according to ASN.1, we |
| // intentionally don't support these large values because there are no |
| // ENUMERATED values in X.509 certs or OCSP this large, and we're trying to |
| // keep the parser simple and fast. |
| const uint8_t DER_ENUMERATED_INVALID_LENGTH[] = { |
| 0x0a, // ENUMERATED |
| 0x02, // length |
| 0x12, 0x34 // value |
| }; |
| Input input(DER_ENUMERATED_INVALID_LENGTH); |
| Reader reader(input); |
| |
| uint8_t value = 0; |
| ASSERT_EQ(Result::ERROR_INVALID_INTEGER_ENCODING, Enumerated(reader, value)); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, EnumeratedInvalidZeroLength) |
| { |
| const uint8_t DER_ENUMERATED_INVALID_ZERO_LENGTH[] = { |
| 0x0a, // ENUMERATED |
| 0x00 // length |
| }; |
| Input input(DER_ENUMERATED_INVALID_ZERO_LENGTH); |
| Reader reader(input); |
| |
| uint8_t value = 0; |
| ASSERT_EQ(Result::ERROR_INVALID_INTEGER_ENCODING, Enumerated(reader, value)); |
| } |
| |
| //////////////////////////////////////// |
| // GeneralizedTime and TimeChoice |
| // |
| // 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. |
| |
| // e.g. TWO_CHARS(53) => '5', '3' |
| #define TWO_CHARS(t) \ |
| static_cast<uint8_t>('0' + (static_cast<uint8_t>(t) / 10u)), \ |
| static_cast<uint8_t>('0' + (static_cast<uint8_t>(t) % 10u)) |
| |
| // Calls TimeChoice on the UTCTime variant of the given generalized time. |
| template <uint16_t LENGTH> |
| Result |
| TimeChoiceForEquivalentUTCTime(const uint8_t (&generalizedTimeDER)[LENGTH], |
| /*out*/ Time& value) |
| { |
| static_assert(LENGTH >= 4, |
| "TimeChoiceForEquivalentUTCTime input too small"); |
| uint8_t utcTimeDER[LENGTH - 2]; |
| utcTimeDER[0] = 0x17; // tag UTCTime |
| utcTimeDER[1] = LENGTH - 1/*tag*/ - 1/*value*/ - 2/*century*/; |
| // Copy the value except for the first two digits of the year |
| for (size_t i = 2; i < LENGTH - 2; ++i) { |
| utcTimeDER[i] = generalizedTimeDER[i + 2]; |
| } |
| |
| Input input(utcTimeDER); |
| Reader reader(input); |
| return TimeChoice(reader, value); |
| } |
| |
| template <uint16_t LENGTH> |
| void |
| ExpectGoodTime(Time expectedValue, |
| const uint8_t (&generalizedTimeDER)[LENGTH]) |
| { |
| // GeneralizedTime |
| { |
| Input input(generalizedTimeDER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Success, GeneralizedTime(reader, value)); |
| EXPECT_EQ(expectedValue, value); |
| } |
| |
| // TimeChoice: GeneralizedTime |
| { |
| Input input(generalizedTimeDER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Success, TimeChoice(reader, value)); |
| EXPECT_EQ(expectedValue, value); |
| } |
| |
| // TimeChoice: UTCTime |
| { |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Success, |
| TimeChoiceForEquivalentUTCTime(generalizedTimeDER, value)); |
| EXPECT_EQ(expectedValue, value); |
| } |
| } |
| |
| template <uint16_t LENGTH> |
| void |
| ExpectBadTime(const uint8_t (&generalizedTimeDER)[LENGTH]) |
| { |
| // GeneralizedTime |
| { |
| Input input(generalizedTimeDER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, GeneralizedTime(reader, value)); |
| } |
| |
| // TimeChoice: GeneralizedTime |
| { |
| Input input(generalizedTimeDER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, TimeChoice(reader, value)); |
| } |
| |
| // TimeChoice: UTCTime |
| { |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, |
| TimeChoiceForEquivalentUTCTime(generalizedTimeDER, value)); |
| } |
| } |
| |
| // Control value: a valid time |
| TEST_F(pkixder_universal_types_tests, ValidControl) |
| { |
| const uint8_t GT_DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '1', '9', '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z' |
| }; |
| ExpectGoodTime(YMDHMS(1991, 5, 6, 16, 45, 40), GT_DER); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeTimeZoneOffset) |
| { |
| const uint8_t DER_GENERALIZED_TIME_OFFSET[] = { |
| 0x18, // Generalized Time |
| 19, // Length = 19 |
| '1', '9', '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', '-', |
| '0', '7', '0', '0' |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_OFFSET); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeInvalidZeroLength) |
| { |
| const uint8_t DER_GENERALIZED_TIME_INVALID_ZERO_LENGTH[] = { |
| 0x18, // GeneralizedTime |
| 0x00 // Length = 0 |
| }; |
| |
| Time value(Time::uninitialized); |
| |
| // GeneralizedTime |
| Input gtBuf(DER_GENERALIZED_TIME_INVALID_ZERO_LENGTH); |
| Reader gt(gtBuf); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, GeneralizedTime(gt, value)); |
| |
| // TimeChoice: GeneralizedTime |
| Input tc_gt_buf(DER_GENERALIZED_TIME_INVALID_ZERO_LENGTH); |
| Reader tc_gt(tc_gt_buf); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, TimeChoice(tc_gt, value)); |
| |
| // TimeChoice: UTCTime |
| const uint8_t DER_UTCTIME_INVALID_ZERO_LENGTH[] = { |
| 0x17, // UTCTime |
| 0x00 // Length = 0 |
| }; |
| Input tc_utc_buf(DER_UTCTIME_INVALID_ZERO_LENGTH); |
| Reader tc_utc(tc_utc_buf); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, TimeChoice(tc_utc, value)); |
| } |
| |
| // A non zulu time should fail |
| TEST_F(pkixder_universal_types_tests, TimeInvalidLocal) |
| { |
| 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' |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_INVALID_LOCAL); |
| } |
| |
| // A time missing seconds and zulu should fail |
| TEST_F(pkixder_universal_types_tests, TimeInvalidTruncated) |
| { |
| 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' |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_INVALID_TRUNCATED); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeNoSeconds) |
| { |
| 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' |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_NO_SECONDS); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeInvalidPrefixedYear) |
| { |
| 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' |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_INVALID_PREFIXED_YEAR); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeTooManyDigits) |
| { |
| const uint8_t DER_GENERALIZED_TIME_TOO_MANY_DIGITS[] = { |
| 0x18, // Generalized Time |
| 16, // Length = 16 |
| '1', '1', '1', '1', '1', '0', '1', '0', '1', '0', '1', '0', '1', '0', '1', 'Z' |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_TOO_MANY_DIGITS); |
| } |
| |
| // In order to ensure we we don't run into any trouble with conversions to and |
| // from time_t we only accept times from 1970 onwards. |
| TEST_F(pkixder_universal_types_tests, GeneralizedTimeYearValidRange) |
| { |
| // Note that by using the last second of the last day of the year, we're also |
| // effectively testing all the accumulated conversions from Gregorian to to |
| // Julian time, including in particular the effects of leap years. |
| |
| for (uint16_t i = 1970; i <= 9999; ++i) { |
| const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| TWO_CHARS(i / 100), TWO_CHARS(i % 100), // YYYY |
| '1', '2', '3', '1', // 12-31 |
| '2', '3', '5', '9', '5', '9', 'Z' // 23:59:59Z |
| }; |
| |
| Time expectedValue = YMDHMS(i, 12, 31, 23, 59, 59); |
| |
| // We have to test GeneralizedTime separately from UTCTime instead of using |
| // ExpectGooDtime because the range of UTCTime is less than the range of |
| // GeneralizedTime. |
| |
| // GeneralizedTime |
| { |
| Input input(DER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Success, GeneralizedTime(reader, value)); |
| EXPECT_EQ(expectedValue, value); |
| } |
| |
| // TimeChoice: GeneralizedTime |
| { |
| Input input(DER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Success, TimeChoice(reader, value)); |
| EXPECT_EQ(expectedValue, value); |
| } |
| |
| // TimeChoice: UTCTime, which is limited to years less than 2049. |
| if (i <= 2049) { |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Success, TimeChoiceForEquivalentUTCTime(DER, value)); |
| EXPECT_EQ(expectedValue, value); |
| } |
| } |
| } |
| |
| // In order to ensure we we don't run into any trouble with conversions to and |
| // from time_t we only accept times from 1970 onwards. |
| TEST_F(pkixder_universal_types_tests, TimeYearInvalid1969) |
| { |
| static const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '1', '9', '6', '9', '1', '2', '3', '1', // !!!1969!!!-12-31 |
| '2', '3', '5', '9', '5', '9', 'Z' // 23:59:59Z |
| }; |
| ExpectBadTime(DER); |
| } |
| |
| static const uint8_t DAYS_IN_MONTH[] = { |
| 0, // unused |
| 31, // January |
| 28, // February (leap years tested separately) |
| 31, // March |
| 30, // April |
| 31, // May |
| 30, // Jun |
| 31, // July |
| 31, // August |
| 30, // September |
| 31, // October |
| 30, // November |
| 31, // December |
| }; |
| |
| TEST_F(pkixder_universal_types_tests, TimeMonthDaysValidRange) |
| { |
| for (uint16_t month = 1; month <= 12; ++month) { |
| for (uint8_t day = 1; day <= DAYS_IN_MONTH[month]; ++day) { |
| const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '1', '5', TWO_CHARS(month), TWO_CHARS(day), // (2015-mm-dd) |
| '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40 |
| }; |
| ExpectGoodTime(YMDHMS(2015, month, day, 16, 45, 40), DER); |
| } |
| } |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMonthInvalid0) |
| { |
| static const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '1', '5', '0', '0', '1', '5', // 2015-!!!00!!!-15 |
| '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40 |
| }; |
| ExpectBadTime(DER); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMonthInvalid13) |
| { |
| const uint8_t DER_GENERALIZED_TIME_13TH_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' |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_13TH_MONTH); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeDayInvalid0) |
| { |
| static const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '1', '5', '0', '1', '0', '0', // 2015-01-!!!00!!! |
| '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40 |
| }; |
| ExpectBadTime(DER); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMonthDayInvalidPastEndOfMonth) |
| { |
| for (int16_t month = 1; month <= 12; ++month) { |
| const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '1', '9', '9', '1', // YYYY 1991 |
| TWO_CHARS(month), // MM |
| TWO_CHARS(1 + (month == 2 ? 29 : DAYS_IN_MONTH[month])), // !!!DD!!! |
| '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40 |
| }; |
| ExpectBadTime(DER); |
| } |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMonthFebLeapYear2016) |
| { |
| static const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '1', '6', '0', '2', '2', '9', // 2016-02-29 |
| '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40 |
| }; |
| ExpectGoodTime(YMDHMS(2016, 2, 29, 16, 45, 40), DER); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMonthFebLeapYear2000) |
| { |
| static const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '0', '0', '0', '2', '2', '9', // 2000-02-29 |
| '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40 |
| }; |
| ExpectGoodTime(YMDHMS(2000, 2, 29, 16, 45, 40), DER); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMonthFebLeapYear2400) |
| { |
| static const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '4', '0', '0', '0', '2', '2', '9', // 2400-02-29 |
| '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40 |
| }; |
| |
| // We don't use ExpectGoodTime here because UTCTime can't represent 2400. |
| |
| Time expectedValue = YMDHMS(2400, 2, 29, 16, 45, 40); |
| |
| // GeneralizedTime |
| { |
| Input input(DER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Success, GeneralizedTime(reader, value)); |
| EXPECT_EQ(expectedValue, value); |
| } |
| |
| // TimeChoice: GeneralizedTime |
| { |
| Input input(DER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Success, TimeChoice(reader, value)); |
| EXPECT_EQ(expectedValue, value); |
| } |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMonthFebNotLeapYear2014) |
| { |
| static const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '1', '4', '0', '2', '2', '9', // 2014-02-29 |
| '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40 |
| }; |
| ExpectBadTime(DER); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMonthFebNotLeapYear2100) |
| { |
| static const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '1', '0', '0', '0', '2', '2', '9', // 2100-02-29 |
| '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40 |
| }; |
| |
| // We don't use ExpectBadTime here because UTCTime can't represent 2100. |
| |
| // GeneralizedTime |
| { |
| Input input(DER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, GeneralizedTime(reader, value)); |
| } |
| |
| // TimeChoice: GeneralizedTime |
| { |
| Input input(DER); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, TimeChoice(reader, value)); |
| } |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeHoursValidRange) |
| { |
| for (uint8_t i = 0; i <= 23; ++i) { |
| const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30) |
| TWO_CHARS(i), '5', '9', '0', '1', 'Z' // HHMMSSZ (!!!!ii!!!!:59:01 Zulu) |
| }; |
| ExpectGoodTime(YMDHMS(2012, 6, 30, i, 59, 1), DER); |
| } |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeHoursInvalid_24_00_00) |
| { |
| static const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30) |
| '2', '4', '0', '0', '0', '0', 'Z' // HHMMSSZ (!!24!!:00:00 Zulu) |
| }; |
| ExpectBadTime(DER); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMinutesValidRange) |
| { |
| for (uint8_t i = 0; i <= 59; ++i) { |
| const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30) |
| '2', '3', TWO_CHARS(i), '0', '1', 'Z' // HHMMSSZ (23:!!!!ii!!!!:01 Zulu) |
| }; |
| ExpectGoodTime(YMDHMS(2012, 6, 30, 23, i, 1), DER); |
| } |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeMinutesInvalid60) |
| { |
| const uint8_t DER[] = { |
| 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) |
| }; |
| ExpectBadTime(DER); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeSecondsValidRange) |
| { |
| for (uint8_t i = 0; i <= 59; ++i) { |
| const uint8_t DER[] = { |
| 0x18, // Generalized Time |
| 15, // Length = 15 |
| '2', '0', '1', '2', '0', '6', '3', '0', // YYYYMMDD (2012-06-30) |
| '2', '3', '5', '9', TWO_CHARS(i), 'Z' // HHMMSSZ (23:59:!!!!ii!!!! Zulu) |
| }; |
| ExpectGoodTime(YMDHMS(2012, 6, 30, 23, 59, i), DER); |
| } |
| } |
| |
| // No Leap Seconds (60) |
| TEST_F(pkixder_universal_types_tests, TimeSecondsInvalid60) |
| { |
| static const uint8_t DER[] = { |
| 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) |
| }; |
| ExpectBadTime(DER); |
| } |
| |
| // No Leap Seconds (61) |
| TEST_F(pkixder_universal_types_tests, TimeSecondsInvalid61) |
| { |
| static const uint8_t DER[] = { |
| 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) |
| }; |
| ExpectBadTime(DER); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeInvalidZulu) |
| { |
| 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 |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_INVALID_ZULU); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeInvalidExtraData) |
| { |
| 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 |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_INVALID_EXTRA_DATA); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeInvalidCenturyChar) |
| { |
| 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) |
| }; |
| |
| // We can't use ExpectBadTime here, because ExpectBadTime requires |
| // consistent results for GeneralizedTime and UTCTime, but the results |
| // for this input are different. |
| |
| // GeneralizedTime |
| { |
| Input input(DER_GENERALIZED_TIME_INVALID_CENTURY_CHAR); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, GeneralizedTime(reader, value)); |
| } |
| |
| // TimeChoice: GeneralizedTime |
| { |
| Input input(DER_GENERALIZED_TIME_INVALID_CENTURY_CHAR); |
| Reader reader(input); |
| Time value(Time::uninitialized); |
| ASSERT_EQ(Result::ERROR_INVALID_DER_TIME, TimeChoice(reader, value)); |
| } |
| |
| // This test is not applicable to TimeChoice: UTCTime |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeInvalidYearChar) |
| { |
| 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) |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_INVALID_YEAR_CHAR); |
| } |
| |
| 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) |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_INVALID_MONTH_CHAR); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeInvalidDayChar) |
| { |
| 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) |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_INVALID_DAY_CHAR); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, TimeInvalidFractionalSeconds) |
| { |
| 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) |
| }; |
| ExpectBadTime(DER_GENERALIZED_TIME_INVALID_FRACTIONAL_SECONDS); |
| } |
| |
| struct IntegerTestParams |
| { |
| ByteString encoded; |
| struct PositiveIntegerParams |
| { |
| Result expectedResult; |
| Input::size_type significantBytesIfValid; |
| } positiveInteger; |
| struct SmallNonnegativeIntegerParams |
| { |
| Result expectedResult; |
| uint8_t valueIfValid; |
| } smallNonnegativeInteger; |
| }; |
| |
| class pkixder_universal_types_tests_Integer |
| : public ::testing::Test |
| , public ::testing::WithParamInterface<IntegerTestParams> |
| { |
| }; |
| |
| ::std::ostream& operator<<(::std::ostream& os, const IntegerTestParams&) |
| { |
| return os << "TODO (bug 1318770)"; |
| } |
| |
| #define INVALID 0xFF |
| |
| static const IntegerTestParams INTEGER_TEST_PARAMS[] = |
| { |
| // Zero is encoded with one value byte of 0x00. |
| { TLV(2, ByteString()), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x00"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Success, 0 } }, |
| |
| // Positive single-byte values |
| { TLV(2, "\x01"), { Success, 1 }, { Success, 1} }, |
| { TLV(2, "\x02"), { Success, 1 }, { Success, 2} }, |
| { TLV(2, "\x7e"), { Success, 1 }, { Success, 0x7e} }, |
| { TLV(2, "\x7f"), { Success, 1 }, { Success, 0x7f} }, |
| |
| // Negative single-byte values |
| { TLV(2, "\x80"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x81"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\xFE"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\xFF"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| |
| // Positive two-byte values not starting with 0x00 |
| { TLV(2, "\x7F\x00"), |
| { Success, 2 }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x01\x00"), |
| { Success, 2 }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x01\x02"), |
| { Success, 2 }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| |
| // Negative two-byte values not starting with 0xFF |
| { TLV(2, "\x80\x00"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x80\x7F"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x80\x80"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x80\xFF"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| |
| // The leading zero is necessary. |
| { TLV(2, "\x00\x80"), |
| { Success, 1}, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x00\x81"), |
| { Success, 1}, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x00\xFF"), |
| { Success, 1}, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| |
| // The leading zero is unnecessary. |
| { TLV(2, "\x00\x01"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\x00\x7F"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| |
| // The leading 0xFF is necessary. |
| { TLV(2, "\xFF\x00"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\xFF\x7F"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| |
| // The leading 0xFF is unnecessary. |
| { TLV(2, "\xFF\x80"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, "\xFF\xFF"), |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| |
| // Truncated values |
| { TLV(2, 1, ByteString(/*missing value*/)), |
| { Result::ERROR_BAD_DER, INVALID }, |
| { Result::ERROR_BAD_DER, INVALID } }, |
| { TLV(2, 3, "\x11\x22" /*truncated*/), |
| { Result::ERROR_BAD_DER, INVALID }, |
| { Result::ERROR_BAD_DER, INVALID } }, |
| { TLV(2, 4, "\x11\x22" /*truncated*/), |
| { Result::ERROR_BAD_DER, INVALID }, |
| { Result::ERROR_BAD_DER, INVALID } }, |
| { TLV(2, 2, "\x00" /*truncated*/), |
| { Result::ERROR_BAD_DER, INVALID }, |
| { Result::ERROR_BAD_DER, INVALID } }, |
| { TLV(2, 2, "\xFF" /*truncated*/), |
| { Result::ERROR_BAD_DER, INVALID }, |
| { Result::ERROR_BAD_DER, INVALID } }, |
| { TLV(2, 3, "\x00\x80" /*truncated*/), |
| { Result::ERROR_BAD_DER, INVALID }, |
| { Result::ERROR_BAD_DER, INVALID } }, |
| { TLV(2, 3, "\xFF\x00" /*truncated*/), |
| { Result::ERROR_BAD_DER, INVALID }, |
| { Result::ERROR_BAD_DER, INVALID } }, |
| |
| // Misc. larger values |
| { TLV(2, 4, "\x11\x22\x33\x44"), |
| { Success, 4 }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| { TLV(2, |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" |
| "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00"), |
| { Success, 256 }, |
| { Result::ERROR_INVALID_INTEGER_ENCODING, INVALID } }, |
| }; |
| |
| TEST_P(pkixder_universal_types_tests_Integer, Integer) |
| { |
| const IntegerTestParams& params(GetParam()); |
| Input input; |
| ASSERT_EQ(Success, input.Init(params.encoded.data(), |
| params.encoded.length())); |
| Reader reader(input); |
| Result expectedResult = params.smallNonnegativeInteger.expectedResult; |
| uint8_t value; |
| ASSERT_EQ(expectedResult, der::Integer(reader, value)); |
| if (expectedResult == Success) { |
| ASSERT_EQ(params.smallNonnegativeInteger.valueIfValid, value); |
| ASSERT_TRUE(reader.AtEnd()); |
| } |
| } |
| |
| TEST_P(pkixder_universal_types_tests_Integer, |
| PositiveInteger_without_significantBytes) |
| { |
| const IntegerTestParams& params(GetParam()); |
| Input input; |
| ASSERT_EQ(Success, input.Init(params.encoded.data(), |
| params.encoded.length())); |
| Reader reader(input); |
| Result expectedResult = params.positiveInteger.expectedResult; |
| Input value; |
| ASSERT_EQ(expectedResult, der::PositiveInteger(reader, value)); |
| if (expectedResult == Success) { |
| Reader anotherReader(input); |
| Input expectedValue; |
| ASSERT_EQ(Success, ExpectTagAndGetValue(anotherReader, |
| der::INTEGER, expectedValue)); |
| ASSERT_TRUE(InputsAreEqual(expectedValue, value)); |
| ASSERT_TRUE(reader.AtEnd()); |
| } |
| } |
| |
| TEST_P(pkixder_universal_types_tests_Integer, |
| PositiveInteger_with_significantBytes) |
| { |
| const IntegerTestParams& params(GetParam()); |
| Input input; |
| ASSERT_EQ(Success, input.Init(params.encoded.data(), |
| params.encoded.length())); |
| Reader reader(input); |
| Result expectedResult = params.positiveInteger.expectedResult; |
| Input value; |
| Input::size_type significantBytes = INVALID; |
| ASSERT_EQ(expectedResult, der::PositiveInteger(reader, value, |
| &significantBytes)); |
| if (expectedResult == Success) { |
| ASSERT_NE(INVALID, params.positiveInteger.significantBytesIfValid); |
| ASSERT_EQ(params.positiveInteger.significantBytesIfValid, |
| significantBytes); |
| |
| Reader anotherReader(input); |
| Input expectedValue; |
| ASSERT_EQ(Success, ExpectTagAndGetValue(anotherReader, |
| der::INTEGER, expectedValue)); |
| ASSERT_TRUE(InputsAreEqual(expectedValue, value)); |
| ASSERT_TRUE(reader.AtEnd()); |
| } |
| } |
| |
| #undef INVALID |
| |
| INSTANTIATE_TEST_CASE_P(pkixder_universal_types_tests_Integer, |
| pkixder_universal_types_tests_Integer, |
| testing::ValuesIn(INTEGER_TEST_PARAMS)); |
| |
| TEST_F(pkixder_universal_types_tests, OptionalIntegerSupportedDefault) |
| { |
| // The input is a BOOLEAN and not INTEGER for the input so we'll not parse |
| // anything and instead use the default value. |
| Input input(DER_BOOLEAN_TRUE); |
| Reader reader(input); |
| |
| long value = 1; |
| ASSERT_EQ(Success, OptionalInteger(reader, -1, value)); |
| ASSERT_EQ(-1, value); |
| bool boolValue; |
| ASSERT_EQ(Success, Boolean(reader, boolValue)); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, OptionalIntegerUnsupportedDefault) |
| { |
| // The same as the previous test, except with an unsupported default value |
| // passed in. |
| Input input(DER_BOOLEAN_TRUE); |
| Reader reader(input); |
| |
| long value; |
| ASSERT_EQ(Result::FATAL_ERROR_INVALID_ARGS, OptionalInteger(reader, 0, value)); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, OptionalIntegerSupportedDefaultAtEnd) |
| { |
| static const uint8_t dummy = 1; |
| Input input; |
| ASSERT_EQ(Success, input.Init(&dummy, 0)); |
| Reader reader(input); |
| |
| long value = 1; |
| ASSERT_EQ(Success, OptionalInteger(reader, -1, value)); |
| ASSERT_EQ(-1, value); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, OptionalIntegerNonDefaultValue) |
| { |
| static const uint8_t DER[] = { |
| 0x02, // INTEGER |
| 0x01, // length |
| 0x00 |
| }; |
| Input input(DER); |
| Reader reader(input); |
| |
| long value = 2; |
| ASSERT_EQ(Success, OptionalInteger(reader, -1, value)); |
| ASSERT_EQ(0, value); |
| ASSERT_TRUE(reader.AtEnd()); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, Null) |
| { |
| const uint8_t DER_NUL[] = { |
| 0x05, |
| 0x00 |
| }; |
| Input input(DER_NUL); |
| Reader reader(input); |
| |
| ASSERT_EQ(Success, Null(reader)); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, NullWithBadLength) |
| { |
| const uint8_t DER_NULL_BAD_LENGTH[] = { |
| 0x05, |
| 0x01, |
| 0x00 |
| }; |
| Input input(DER_NULL_BAD_LENGTH); |
| Reader reader(input); |
| |
| ASSERT_EQ(Result::ERROR_BAD_DER, Null(reader)); |
| } |
| |
| TEST_F(pkixder_universal_types_tests, OID) |
| { |
| const uint8_t DER_VALID_OID[] = { |
| 0x06, |
| 0x09, |
| 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01 |
| }; |
| Input input(DER_VALID_OID); |
| Reader reader(input); |
| |
| const uint8_t expectedOID[] = { |
| 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01 |
| }; |
| |
| ASSERT_EQ(Success, OID(reader, expectedOID)); |
| } |