michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* Copyright 2013 Mozilla Foundation michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "pkix/bind.h" michael@0: #include "pkixder.h" michael@0: michael@0: using namespace mozilla::pkix::der; michael@0: michael@0: namespace { michael@0: michael@0: class pkixder_input_tests : public ::testing::Test michael@0: { michael@0: protected: michael@0: virtual void SetUp() michael@0: { michael@0: PR_SetError(0, 0); michael@0: } michael@0: }; michael@0: michael@0: const uint8_t DER_SEQUENCE_OF_INT8[] = { michael@0: 0x30, // SEQUENCE michael@0: 0x09, // length michael@0: 0x02, 0x01, 0x01, // INTEGER length 1 value 0x01 michael@0: 0x02, 0x01, 0x02, // INTEGER length 1 value 0x02 michael@0: 0x02, 0x01, 0x03 // INTEGER length 1 value 0x03 michael@0: }; michael@0: michael@0: const uint8_t DER_TRUNCATED_SEQUENCE_OF_INT8[] = { michael@0: 0x30, // SEQUENCE michael@0: 0x09, // length michael@0: 0x02, 0x01, 0x01, // INTEGER length 1 value 0x01 michael@0: 0x02, 0x01, 0x02 // INTEGER length 1 value 0x02 michael@0: // MISSING DATA HERE ON PURPOSE michael@0: }; michael@0: michael@0: const uint8_t DER_OVERRUN_SEQUENCE_OF_INT8[] = { michael@0: 0x30, // SEQUENCE michael@0: 0x09, // length michael@0: 0x02, 0x01, 0x01, // INTEGER length 1 value 0x01 michael@0: 0x02, 0x01, 0x02, // INTEGER length 1 value 0x02 michael@0: 0x02, 0x02, 0xFF, 0x03 // INTEGER length 2 value 0xFF03 michael@0: }; michael@0: michael@0: const uint8_t DER_INT16[] = { michael@0: 0x02, // INTEGER michael@0: 0x02, // length michael@0: 0x12, 0x34 // 0x1234 michael@0: }; michael@0: michael@0: TEST_F(pkixder_input_tests, FailWithError) michael@0: { michael@0: ASSERT_EQ(Failure, Fail(SEC_ERROR_BAD_DER)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: michael@0: ASSERT_EQ(Failure, Fail(SEC_ERROR_INVALID_ARGS)); michael@0: ASSERT_EQ(SEC_ERROR_INVALID_ARGS, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputInit) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputInitWithNullPointerOrZeroLength) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Failure, input.Init(nullptr, 0)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: michael@0: ASSERT_EQ(Failure, input.Init(nullptr, 100)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: michael@0: // Is this a bug? michael@0: ASSERT_EQ(Success, input.Init((const uint8_t*) "hello", 0)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputInitWithLargeData) michael@0: { michael@0: Input input; michael@0: // Data argument length does not matter, it is not touched, just michael@0: // needs to be non-null michael@0: ASSERT_EQ(Failure, input.Init((const uint8_t*) "", 0xffff+1)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: michael@0: ASSERT_EQ(Success, input.Init((const uint8_t*) "", 0xffff)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputInitMultipleTimes) michael@0: { michael@0: Input input; michael@0: michael@0: ASSERT_EQ(Success, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: michael@0: ASSERT_EQ(Failure, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: ASSERT_EQ(SEC_ERROR_INVALID_ARGS, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectSuccess) michael@0: { michael@0: Input input; michael@0: michael@0: ASSERT_EQ(Success, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: ASSERT_EQ(Success, michael@0: input.Expect(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: ASSERT_TRUE(input.AtEnd()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectMismatch) michael@0: { michael@0: Input input; michael@0: michael@0: ASSERT_EQ(Success, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: michael@0: const uint8_t expected[] = { 0x11, 0x22 }; michael@0: ASSERT_EQ(Failure, input.Expect(expected, sizeof expected)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectTooMuch) michael@0: { michael@0: Input input; michael@0: michael@0: const uint8_t der[] = { 0x11, 0x22 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: const uint8_t expected[] = { 0x11, 0x22, 0x33 }; michael@0: ASSERT_EQ(Failure, input.Expect(expected, sizeof expected)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, PeekWithinBounds) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x11 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: ASSERT_TRUE(input.Peek(0x11)); michael@0: ASSERT_FALSE(input.Peek(0x22)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, PeekPastBounds) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22 }; michael@0: ASSERT_EQ(Success, input.Init(der, 1)); michael@0: michael@0: uint8_t readByte; michael@0: ASSERT_EQ(Success, input.Read(readByte)); michael@0: ASSERT_EQ(0x11, readByte); michael@0: ASSERT_FALSE(input.Peek(0x22)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ReadByte) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: uint8_t readByte1; michael@0: ASSERT_EQ(Success, input.Read(readByte1)); michael@0: ASSERT_EQ(0x11, readByte1); michael@0: michael@0: uint8_t readByte2; michael@0: ASSERT_EQ(Success, input.Read(readByte2)); michael@0: ASSERT_EQ(0x22, readByte2); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ReadBytePastEnd) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22 }; michael@0: // Initialize with too-short length michael@0: ASSERT_EQ(Success, input.Init(der, 1)); michael@0: michael@0: uint8_t readByte1 = 0; michael@0: ASSERT_EQ(Success, input.Read(readByte1)); michael@0: ASSERT_EQ(0x11, readByte1); michael@0: michael@0: uint8_t readByte2 = 0; michael@0: ASSERT_EQ(Failure, input.Read(readByte2)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: ASSERT_NE(0x22, readByte2); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ReadByteWrapAroundPointer) michael@0: { michael@0: // The original implementation of our buffer read overflow checks was michael@0: // susceptible to integer overflows which could make the checks ineffective. michael@0: // This attempts to verify that we've fixed that. Unfortunately, decrementing michael@0: // a null pointer is undefined behavior according to the C++ language spec., michael@0: // but this should catch the problem on at least some compilers, if not all of michael@0: // them. michael@0: const uint8_t* der = nullptr; michael@0: --der; michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(der, 0)); michael@0: uint8_t b; michael@0: ASSERT_EQ(Failure, input.Read(b)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ReadWord) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: uint16_t readWord1 = 0; michael@0: ASSERT_EQ(Success, input.Read(readWord1)); michael@0: ASSERT_EQ(0x1122, readWord1); michael@0: michael@0: uint16_t readWord2 = 0; michael@0: ASSERT_EQ(Success, input.Read(readWord2)); michael@0: ASSERT_EQ(0x3344, readWord2); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ReadWordPastEnd) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: // Initialize with too-short length michael@0: ASSERT_EQ(Success, input.Init(der, 2)); michael@0: michael@0: uint16_t readWord1 = 0; michael@0: ASSERT_EQ(Success, input.Read(readWord1)); michael@0: ASSERT_EQ(0x1122, readWord1); michael@0: michael@0: uint16_t readWord2 = 0; michael@0: ASSERT_EQ(Failure, input.Read(readWord2)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: ASSERT_NE(0x3344, readWord2); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ReadWordWithInsufficentData) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22 }; michael@0: ASSERT_EQ(Success, input.Init(der, 1)); michael@0: michael@0: uint16_t readWord1 = 0; michael@0: ASSERT_EQ(Failure, input.Read(readWord1)); michael@0: ASSERT_NE(0x1122, readWord1); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ReadWordWrapAroundPointer) michael@0: { michael@0: // The original implementation of our buffer read overflow checks was michael@0: // susceptible to integer overflows which could make the checks ineffective. michael@0: // This attempts to verify that we've fixed that. Unfortunately, decrementing michael@0: // a null pointer is undefined behavior according to the C++ language spec., michael@0: // but this should catch the problem on at least some compilers, if not all of michael@0: // them. michael@0: const uint8_t* der = nullptr; michael@0: --der; michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(der, 0)); michael@0: uint16_t b; michael@0: ASSERT_EQ(Failure, input.Read(b)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputSkip) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: ASSERT_EQ(Success, input.Skip(1)); michael@0: michael@0: uint8_t readByte1 = 0; michael@0: ASSERT_EQ(Success, input.Read(readByte1)); michael@0: ASSERT_EQ(0x22, readByte1); michael@0: michael@0: ASSERT_EQ(Success, input.Skip(1)); michael@0: michael@0: uint8_t readByte2 = 0; michael@0: ASSERT_EQ(Success, input.Read(readByte2)); michael@0: ASSERT_EQ(0x44, readByte2); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputSkipToEnd) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: ASSERT_EQ(Success, input.Skip(sizeof der)); michael@0: ASSERT_TRUE(input.AtEnd()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputSkipPastEnd) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: ASSERT_EQ(Failure, input.Skip(sizeof der + 1)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputSkipToNewInput) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x01, 0x02, 0x03, 0x04 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: Input skippedInput; michael@0: ASSERT_EQ(Success, input.Skip(3, skippedInput)); michael@0: michael@0: uint8_t readByte1 = 0; michael@0: ASSERT_EQ(Success, input.Read(readByte1)); michael@0: ASSERT_EQ(0x04, readByte1); michael@0: michael@0: ASSERT_TRUE(input.AtEnd()); michael@0: michael@0: // Input has no Remaining() or Length() so we simply read the bytes michael@0: // and then expect to be at the end. michael@0: michael@0: for (uint8_t i = 1; i <= 3; ++i) { michael@0: uint8_t readByte = 0; michael@0: ASSERT_EQ(Success, skippedInput.Read(readByte)); michael@0: ASSERT_EQ(i, readByte); michael@0: } michael@0: michael@0: ASSERT_TRUE(skippedInput.AtEnd()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputSkipToNewInputPastEnd) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: Input skippedInput; michael@0: ASSERT_EQ(Failure, input.Skip(sizeof der * 2, skippedInput)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, InputSkipToSECItem) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: const uint8_t expectedItemData[] = { 0x11, 0x22, 0x33 }; michael@0: michael@0: SECItem item; michael@0: ASSERT_EQ(Success, input.Skip(sizeof expectedItemData, item)); michael@0: ASSERT_EQ(siBuffer, item.type); michael@0: ASSERT_EQ(sizeof expectedItemData, item.len); michael@0: ASSERT_EQ(der, item.data); michael@0: ASSERT_EQ(0, memcmp(item.data, expectedItemData, sizeof expectedItemData)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, SkipWrapAroundPointer) michael@0: { michael@0: // The original implementation of our buffer read overflow checks was michael@0: // susceptible to integer overflows which could make the checks ineffective. michael@0: // This attempts to verify that we've fixed that. Unfortunately, decrementing michael@0: // a null pointer is undefined behavior according to the C++ language spec., michael@0: // but this should catch the problem on at least some compilers, if not all of michael@0: // them. michael@0: const uint8_t* der = nullptr; michael@0: --der; michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(der, 0)); michael@0: ASSERT_EQ(Failure, input.Skip(1)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, SkipToSECItemPastEnd) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: SECItem skippedSECItem; michael@0: ASSERT_EQ(Failure, input.Skip(sizeof der + 1, skippedSECItem)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, Skip) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: michael@0: ASSERT_EQ(Success, Skip(input, SEQUENCE)); michael@0: ASSERT_EQ(Success, End(input)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, SkipWithTruncatedData) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_TRUNCATED_SEQUENCE_OF_INT8, michael@0: sizeof DER_TRUNCATED_SEQUENCE_OF_INT8)); michael@0: michael@0: ASSERT_EQ(Failure, Skip(input, SEQUENCE)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, SkipWithOverrunData) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_OVERRUN_SEQUENCE_OF_INT8, michael@0: sizeof DER_OVERRUN_SEQUENCE_OF_INT8)); michael@0: ASSERT_EQ(Success, Skip(input, SEQUENCE)); michael@0: ASSERT_EQ(Failure, End(input)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, AtEndOnUnInitializedInput) michael@0: { michael@0: Input input; michael@0: ASSERT_TRUE(input.AtEnd()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, AtEndAtBeginning) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: ASSERT_FALSE(input.AtEnd()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, AtEndAtEnd) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: ASSERT_EQ(Success, input.Skip(sizeof der)); michael@0: ASSERT_TRUE(input.AtEnd()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, MarkAndGetSECItem) michael@0: { michael@0: Input input; michael@0: const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 }; michael@0: ASSERT_EQ(Success, input.Init(der, sizeof der)); michael@0: michael@0: Input::Mark mark = input.GetMark(); michael@0: michael@0: const uint8_t expectedItemData[] = { 0x11, 0x22, 0x33 }; michael@0: michael@0: ASSERT_EQ(Success, input.Skip(sizeof expectedItemData)); michael@0: michael@0: SECItem item; michael@0: memset(&item, 0x00, sizeof item); michael@0: michael@0: ASSERT_TRUE(input.GetSECItem(siBuffer, mark, item)); michael@0: ASSERT_EQ(siBuffer, item.type); michael@0: ASSERT_EQ(sizeof expectedItemData, item.len); michael@0: ASSERT_TRUE(item.data); michael@0: ASSERT_EQ(0, memcmp(item.data, expectedItemData, sizeof expectedItemData)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectTagAndLength) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: michael@0: ASSERT_EQ(Success, ExpectTagAndLength(input, SEQUENCE, michael@0: sizeof DER_SEQUENCE_OF_INT8 - 2)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectTagAndLengthWithWrongLength) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16)); michael@0: michael@0: // Wrong length michael@0: ASSERT_EQ(Failure, ExpectTagAndLength(input, INTEGER, 4)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectTagAndLengthWithWrongTag) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16)); michael@0: michael@0: // Wrong type michael@0: ASSERT_EQ(Failure, ExpectTagAndLength(input, OCTET_STRING, 2)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectTagAndGetLength) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: michael@0: uint16_t length = 0; michael@0: ASSERT_EQ(Success, ExpectTagAndGetLength(input, SEQUENCE, length)); michael@0: ASSERT_EQ(sizeof DER_SEQUENCE_OF_INT8 - 2, length); michael@0: ASSERT_EQ(Success, input.Skip(length)); michael@0: ASSERT_TRUE(input.AtEnd()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectTagAndGetLengthWithWrongTag) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: michael@0: uint16_t length = 0; michael@0: ASSERT_EQ(Failure, ExpectTagAndGetLength(input, INTEGER, length)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectTagAndGetLengthWithWrongLength) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_TRUNCATED_SEQUENCE_OF_INT8, michael@0: sizeof DER_TRUNCATED_SEQUENCE_OF_INT8)); michael@0: michael@0: uint16_t length = 0; michael@0: ASSERT_EQ(Failure, ExpectTagAndGetLength(input, SEQUENCE, length)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectTagAndIgnoreLength) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16)); michael@0: ASSERT_EQ(Success, ExpectTagAndIgnoreLength(input, INTEGER)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, ExpectTagAndIgnoreLengthWithWrongTag) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16)); michael@0: michael@0: ASSERT_EQ(Failure, ExpectTagAndIgnoreLength(input, OCTET_STRING)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, EndAtEnd) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16)); michael@0: ASSERT_EQ(Success, input.Skip(4)); michael@0: ASSERT_EQ(Success, End(input)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, EndBeforeEnd) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16)); michael@0: ASSERT_EQ(Success, input.Skip(2)); michael@0: ASSERT_EQ(Failure, End(input)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, EndAtBeginning) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16)); michael@0: ASSERT_EQ(Failure, End(input)); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: } michael@0: michael@0: // TODO: Need tests for Nested too? michael@0: michael@0: Result NestedOfHelper(Input& input, std::vector& readValues) michael@0: { michael@0: uint8_t value = 0; michael@0: if (input.Read(value) != Success) { michael@0: return Failure; michael@0: } michael@0: readValues.push_back(value); michael@0: return Success; michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, NestedOf) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, michael@0: input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8)); michael@0: michael@0: std::vector readValues; michael@0: ASSERT_EQ(Success, michael@0: NestedOf(input, SEQUENCE, INTEGER, MustNotBeEmpty, michael@0: mozilla::pkix::bind(NestedOfHelper, mozilla::pkix::_1, michael@0: mozilla::pkix::ref(readValues)))); michael@0: ASSERT_EQ((size_t) 3, readValues.size()); michael@0: ASSERT_EQ(0x01, readValues[0]); michael@0: ASSERT_EQ(0x02, readValues[1]); michael@0: ASSERT_EQ(0x03, readValues[2]); michael@0: ASSERT_EQ(Success, End(input)); michael@0: } michael@0: michael@0: TEST_F(pkixder_input_tests, NestedOfWithTruncatedData) michael@0: { michael@0: Input input; michael@0: ASSERT_EQ(Success, input.Init(DER_TRUNCATED_SEQUENCE_OF_INT8, michael@0: sizeof DER_TRUNCATED_SEQUENCE_OF_INT8)); michael@0: michael@0: std::vector readValues; michael@0: ASSERT_EQ(Failure, michael@0: NestedOf(input, SEQUENCE, INTEGER, MustNotBeEmpty, michael@0: mozilla::pkix::bind(NestedOfHelper, mozilla::pkix::_1, michael@0: mozilla::pkix::ref(readValues)))); michael@0: ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); michael@0: ASSERT_EQ((size_t) 0, readValues.size()); michael@0: } michael@0: } // unnamed namespace