Bug 968490: Add mozilla::pkix::der unit tests (r=cviecco)

This commit is contained in:
Stefan Arentz 2014-03-26 16:00:03 -07:00
parent 40dbda7fc1
commit c929461f38
6 changed files with 1293 additions and 3 deletions

View File

@ -189,13 +189,14 @@ public:
Mark GetMark() const { return Mark(input); }
void GetSECItem(SECItemType type, const Mark& mark, /*out*/ SECItem& item)
bool GetSECItem(SECItemType type, const Mark& mark, /*out*/ SECItem& item)
{
PR_ASSERT(mark.mMark < input);
item.type = type;
item.data = const_cast<uint8_t*>(mark.mMark);
// TODO: bounds check
// TODO: Return false if bounds check fails
item.len = input - mark.mMark;
return true;
}
private:

View File

@ -17,7 +17,8 @@ LOCAL_INCLUDES += [
'include',
]
DIRS += [
TEST_DIRS += [
'test/gtest',
'test/lib',
]

View File

@ -0,0 +1,22 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
LIBRARY_NAME = 'mozillapkix_gtest'
SOURCES += [
'pkixder_input_tests.cpp',
'pkixder_pki_types_tests.cpp',
'pkixder_universal_types_tests.cpp',
]
LOCAL_INCLUDES += [
'../../include',
'../../lib',
]
FINAL_LIBRARY='xul-gtest'
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -0,0 +1,577 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* Copyright 2013 Mozilla Foundation
*
* 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 <functional>
#include <vector>
#include <gtest/gtest.h>
#include "pkix/bind.h"
#include "pkixder.h"
using namespace mozilla::pkix::der;
namespace {
class pkixder_input_tests : public ::testing::Test
{
protected:
virtual void SetUp()
{
PR_SetError(0, 0);
}
};
const uint8_t DER_SEQUENCE_OF_INT8[] = {
0x30, // SEQUENCE
0x09, // length
0x02, 0x01, 0x01, // INTEGER length 1 value 0x01
0x02, 0x01, 0x02, // INTEGER length 1 value 0x02
0x02, 0x01, 0x03 // INTEGER length 1 value 0x03
};
const uint8_t DER_TRUNCATED_SEQUENCE_OF_INT8[] = {
0x30, // SEQUENCE
0x09, // length
0x02, 0x01, 0x01, // INTEGER length 1 value 0x01
0x02, 0x01, 0x02 // INTEGER length 1 value 0x02
// MISSING DATA HERE ON PURPOSE
};
const uint8_t DER_OVERRUN_SEQUENCE_OF_INT8[] = {
0x30, // SEQUENCE
0x09, // length
0x02, 0x01, 0x01, // INTEGER length 1 value 0x01
0x02, 0x01, 0x02, // INTEGER length 1 value 0x02
0x02, 0x02, 0xFF, 0x03 // INTEGER length 2 value 0xFF03
};
const uint8_t DER_INT16[] = {
0x02, // INTEGER
0x02, // length
0x12, 0x34 // 0x1234
};
TEST_F(pkixder_input_tests, FailWithError)
{
ASSERT_EQ(Failure, Fail(SEC_ERROR_BAD_DER));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
ASSERT_EQ(Failure, Fail(SEC_ERROR_INVALID_ARGS));
ASSERT_EQ(SEC_ERROR_INVALID_ARGS, PR_GetError());
}
TEST_F(pkixder_input_tests, InputInit)
{
Input input;
ASSERT_EQ(Success,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
}
TEST_F(pkixder_input_tests, InputInitWithNullPointerOrZeroLength)
{
Input input;
ASSERT_EQ(Failure, input.Init(nullptr, 0));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
ASSERT_EQ(Failure, input.Init(nullptr, 100));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
// Is this a bug?
ASSERT_EQ(Success, input.Init((const uint8_t*) "hello", 0));
}
TEST_F(pkixder_input_tests, InputInitWithLargeData)
{
Input input;
// Data argument length does not matter, it is not touched, just
// needs to be non-null
ASSERT_EQ(Failure, input.Init((const uint8_t*) "", 0xffff+1));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
ASSERT_EQ(Success, input.Init((const uint8_t*) "", 0xffff));
}
TEST_F(pkixder_input_tests, InputInitMultipleTimes)
{
Input input;
ASSERT_EQ(Success,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
ASSERT_EQ(Failure,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
ASSERT_EQ(SEC_ERROR_INVALID_ARGS, PR_GetError());
}
TEST_F(pkixder_input_tests, ExpectSuccess)
{
Input input;
ASSERT_EQ(Success,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
ASSERT_EQ(Success,
input.Expect(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
ASSERT_TRUE(input.AtEnd());
}
TEST_F(pkixder_input_tests, ExpectMismatch)
{
Input input;
ASSERT_EQ(Success,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
const uint8_t expected[] = { 0x11, 0x22 };
ASSERT_EQ(Failure, input.Expect(expected, sizeof expected));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, ExpectTooMuch)
{
Input input;
const uint8_t der[] = { 0x11, 0x22 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
const uint8_t expected[] = { 0x11, 0x22, 0x33 };
ASSERT_EQ(Failure, input.Expect(expected, sizeof expected));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, PeekWithinBounds)
{
Input input;
const uint8_t der[] = { 0x11, 0x11 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
ASSERT_TRUE(input.Peek(0x11));
ASSERT_FALSE(input.Peek(0x22));
}
TEST_F(pkixder_input_tests, PeekPastBounds)
{
Input input;
const uint8_t der[] = { 0x11, 0x22 };
ASSERT_EQ(Success, input.Init(der, 1));
uint8_t readByte;
ASSERT_EQ(Success, input.Read(readByte));
ASSERT_EQ(0x11, readByte);
ASSERT_FALSE(input.Peek(0x22));
}
TEST_F(pkixder_input_tests, ReadByte)
{
Input input;
const uint8_t der[] = { 0x11, 0x22 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
uint8_t readByte1;
ASSERT_EQ(Success, input.Read(readByte1));
ASSERT_EQ(0x11, readByte1);
uint8_t readByte2;
ASSERT_EQ(Success, input.Read(readByte2));
ASSERT_EQ(0x22, readByte2);
}
TEST_F(pkixder_input_tests, ReadBytePastEnd)
{
Input input;
const uint8_t der[] = { 0x11, 0x22 };
// Initialize with too-short length
ASSERT_EQ(Success, input.Init(der, 1));
uint8_t readByte1 = 0;
ASSERT_EQ(Success, input.Read(readByte1));
ASSERT_EQ(0x11, readByte1);
uint8_t readByte2 = 0;
ASSERT_EQ(Failure, input.Read(readByte2));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
ASSERT_NE(0x22, readByte2);
}
TEST_F(pkixder_input_tests, ReadWord)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
uint16_t readWord1 = 0;
ASSERT_EQ(Success, input.Read(readWord1));
ASSERT_EQ(0x1122, readWord1);
uint16_t readWord2 = 0;
ASSERT_EQ(Success, input.Read(readWord2));
ASSERT_EQ(0x3344, readWord2);
}
TEST_F(pkixder_input_tests, ReadWordPastEnd)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
// Initialize with too-short length
ASSERT_EQ(Success, input.Init(der, 2));
uint16_t readWord1 = 0;
ASSERT_EQ(Success, input.Read(readWord1));
ASSERT_EQ(0x1122, readWord1);
uint16_t readWord2 = 0;
ASSERT_EQ(Failure, input.Read(readWord2));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
ASSERT_NE(0x3344, readWord2);
}
TEST_F(pkixder_input_tests, ReadWordWithInsufficentData)
{
Input input;
const uint8_t der[] = { 0x11, 0x22 };
ASSERT_EQ(Success, input.Init(der, 1));
uint16_t readWord1 = 0;
ASSERT_EQ(Failure, input.Read(readWord1));
ASSERT_NE(0x1122, readWord1);
}
TEST_F(pkixder_input_tests, InputSkip)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
ASSERT_EQ(Success, input.Skip(1));
uint8_t readByte1 = 0;
ASSERT_EQ(Success, input.Read(readByte1));
ASSERT_EQ(0x22, readByte1);
ASSERT_EQ(Success, input.Skip(1));
uint8_t readByte2 = 0;
ASSERT_EQ(Success, input.Read(readByte2));
ASSERT_EQ(0x44, readByte2);
}
TEST_F(pkixder_input_tests, InputSkipToEnd)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
ASSERT_EQ(Success, input.Skip(sizeof der));
ASSERT_TRUE(input.AtEnd());
}
TEST_F(pkixder_input_tests, InputSkipPastEnd)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
ASSERT_EQ(Failure, input.Skip(sizeof der + 1));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, InputSkipToNewInput)
{
Input input;
const uint8_t der[] = { 0x01, 0x02, 0x03, 0x04 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
Input skippedInput;
ASSERT_EQ(Success, input.Skip(3, skippedInput));
uint8_t readByte1 = 0;
ASSERT_EQ(Success, input.Read(readByte1));
ASSERT_EQ(0x04, readByte1);
ASSERT_TRUE(input.AtEnd());
// Input has no Remaining() or Length() so we simply read the bytes
// and then expect to be at the end.
for (uint8_t i = 1; i <= 3; ++i) {
uint8_t readByte = 0;
ASSERT_EQ(Success, skippedInput.Read(readByte));
ASSERT_EQ(i, readByte);
}
ASSERT_TRUE(skippedInput.AtEnd());
}
TEST_F(pkixder_input_tests, InputSkipToNewInputPastEnd)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
Input skippedInput;
ASSERT_EQ(Failure, input.Skip(sizeof der * 2, skippedInput));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, InputSkipToSECItem)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
const uint8_t expectedItemData[] = { 0x11, 0x22, 0x33 };
SECItem item;
ASSERT_EQ(Success, input.Skip(sizeof expectedItemData, item));
ASSERT_EQ(siBuffer, item.type);
ASSERT_EQ(sizeof expectedItemData, item.len);
ASSERT_EQ(der, item.data);
ASSERT_EQ(0, memcmp(item.data, expectedItemData, sizeof expectedItemData));
}
TEST_F(pkixder_input_tests, SkipToSECItemPastEnd)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
SECItem skippedSECItem;
ASSERT_EQ(Failure, input.Skip(sizeof der + 1, skippedSECItem));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, Skip)
{
Input input;
ASSERT_EQ(Success,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
ASSERT_EQ(Success, Skip(input, SEQUENCE));
ASSERT_EQ(Success, End(input));
}
TEST_F(pkixder_input_tests, SkipWithTruncatedData)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_TRUNCATED_SEQUENCE_OF_INT8,
sizeof DER_TRUNCATED_SEQUENCE_OF_INT8));
ASSERT_EQ(Failure, Skip(input, SEQUENCE));
}
TEST_F(pkixder_input_tests, SkipWithOverrunData)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_OVERRUN_SEQUENCE_OF_INT8,
sizeof DER_OVERRUN_SEQUENCE_OF_INT8));
ASSERT_EQ(Success, Skip(input, SEQUENCE));
ASSERT_EQ(Failure, End(input));
}
TEST_F(pkixder_input_tests, AtEndOnUnInitializedInput)
{
Input input;
ASSERT_TRUE(input.AtEnd());
}
TEST_F(pkixder_input_tests, AtEndAtBeginning)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
ASSERT_FALSE(input.AtEnd());
}
TEST_F(pkixder_input_tests, AtEndAtEnd)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
ASSERT_EQ(Success, input.Skip(sizeof der));
ASSERT_TRUE(input.AtEnd());
}
TEST_F(pkixder_input_tests, MarkAndGetSECItem)
{
Input input;
const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
Input::Mark mark = input.GetMark();
const uint8_t expectedItemData[] = { 0x11, 0x22, 0x33 };
ASSERT_EQ(Success, input.Skip(sizeof expectedItemData));
SECItem item;
memset(&item, 0x00, sizeof item);
ASSERT_TRUE(input.GetSECItem(siBuffer, mark, item));
ASSERT_EQ(siBuffer, item.type);
ASSERT_EQ(sizeof expectedItemData, item.len);
ASSERT_TRUE(item.data);
ASSERT_EQ(0, memcmp(item.data, expectedItemData, sizeof expectedItemData));
}
TEST_F(pkixder_input_tests, ExpectTagAndLength)
{
Input input;
ASSERT_EQ(Success,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
ASSERT_EQ(Success, ExpectTagAndLength(input, SEQUENCE,
sizeof DER_SEQUENCE_OF_INT8 - 2));
}
TEST_F(pkixder_input_tests, ExpectTagAndLengthWithWrongLength)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16));
// Wrong length
ASSERT_EQ(Failure, ExpectTagAndLength(input, INTEGER, 4));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, ExpectTagAndLengthWithWrongTag)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16));
// Wrong type
ASSERT_EQ(Failure, ExpectTagAndLength(input, OCTET_STRING, 2));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, ExpectTagAndGetLength)
{
Input input;
ASSERT_EQ(Success,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
uint16_t length = 0;
ASSERT_EQ(Success, ExpectTagAndGetLength(input, SEQUENCE, length));
ASSERT_EQ(sizeof DER_SEQUENCE_OF_INT8 - 2, length);
ASSERT_EQ(Success, input.Skip(length));
ASSERT_TRUE(input.AtEnd());
}
TEST_F(pkixder_input_tests, ExpectTagAndGetLengthWithWrongTag)
{
Input input;
ASSERT_EQ(Success,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
uint16_t length = 0;
ASSERT_EQ(Failure, ExpectTagAndGetLength(input, INTEGER, length));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, ExpectTagAndGetLengthWithWrongLength)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_TRUNCATED_SEQUENCE_OF_INT8,
sizeof DER_TRUNCATED_SEQUENCE_OF_INT8));
uint16_t length = 0;
ASSERT_EQ(Failure, ExpectTagAndGetLength(input, SEQUENCE, length));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, ExpectTagAndIgnoreLength)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16));
ASSERT_EQ(Success, ExpectTagAndIgnoreLength(input, INTEGER));
}
TEST_F(pkixder_input_tests, ExpectTagAndIgnoreLengthWithWrongTag)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16));
ASSERT_EQ(Failure, ExpectTagAndIgnoreLength(input, OCTET_STRING));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, EndAtEnd)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16));
ASSERT_EQ(Success, input.Skip(4));
ASSERT_EQ(Success, End(input));
}
TEST_F(pkixder_input_tests, EndBeforeEnd)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16));
ASSERT_EQ(Success, input.Skip(2));
ASSERT_EQ(Failure, End(input));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_input_tests, EndAtBeginning)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_INT16, sizeof DER_INT16));
ASSERT_EQ(Failure, End(input));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
// TODO: Need tests for Nested too?
Result NestedOfHelper(Input& input, std::vector<uint8_t>& readValues)
{
uint8_t value = 0;
if (input.Read(value) != Success) {
return Failure;
}
readValues.push_back(value);
return Success;
}
TEST_F(pkixder_input_tests, NestedOf)
{
Input input;
ASSERT_EQ(Success,
input.Init(DER_SEQUENCE_OF_INT8, sizeof DER_SEQUENCE_OF_INT8));
std::vector<uint8_t> readValues;
ASSERT_EQ(Success,
NestedOf(input, SEQUENCE, INTEGER, MustNotBeEmpty,
mozilla::pkix::bind(NestedOfHelper, mozilla::pkix::_1,
mozilla::pkix::ref(readValues))));
ASSERT_EQ((size_t) 3, readValues.size());
ASSERT_EQ(0x01, readValues[0]);
ASSERT_EQ(0x02, readValues[1]);
ASSERT_EQ(0x03, readValues[2]);
ASSERT_EQ(Success, End(input));
}
TEST_F(pkixder_input_tests, NestedOfWithTruncatedData)
{
Input input;
ASSERT_EQ(Success, input.Init(DER_TRUNCATED_SEQUENCE_OF_INT8,
sizeof DER_TRUNCATED_SEQUENCE_OF_INT8));
std::vector<uint8_t> readValues;
ASSERT_EQ(Failure,
NestedOf(input, SEQUENCE, INTEGER, MustNotBeEmpty,
mozilla::pkix::bind(NestedOfHelper, mozilla::pkix::_1,
mozilla::pkix::ref(readValues))));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
ASSERT_EQ((size_t) 0, readValues.size());
}
} // unnamed namespace

View File

@ -0,0 +1,264 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* Copyright 2013 Mozilla Foundation
*
* 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 <functional>
#include <vector>
#include <gtest/gtest.h>
#include "pkix/bind.h"
#include "pkixder.h"
using namespace mozilla::pkix::der;
namespace {
class pkixder_pki_types_tests : public ::testing::Test
{
protected:
virtual void SetUp()
{
PR_SetError(0, 0);
}
};
TEST_F(pkixder_pki_types_tests, AlgorithmIdentifierNoParams)
{
const uint8_t DER_ALGORITHM_IDENTIFIER_NO_PARAMS[] = {
0x06, 0x04, 0xde, 0xad, 0xbe, 0xef // OID
};
Input input;
ASSERT_EQ(Success, input.Init(DER_ALGORITHM_IDENTIFIER_NO_PARAMS,
sizeof DER_ALGORITHM_IDENTIFIER_NO_PARAMS));
const uint8_t expectedAlgorithmID[] = {
0xde, 0xad, 0xbe, 0xef
};
SECAlgorithmID algorithmID;
ASSERT_EQ(Success, AlgorithmIdentifier(input, algorithmID));
ASSERT_EQ(sizeof expectedAlgorithmID, algorithmID.algorithm.len);
ASSERT_EQ(0, memcmp(algorithmID.algorithm.data, expectedAlgorithmID,
sizeof expectedAlgorithmID));
ASSERT_EQ(0, algorithmID.parameters.len);
ASSERT_FALSE(algorithmID.parameters.data);
}
TEST_F(pkixder_pki_types_tests, AlgorithmIdentifierNullParams)
{
const uint8_t DER_ALGORITHM_IDENTIFIER_NULL_PARAMS[] = {
0x30, 0x08, // SEQUENCE
0x06, 0x04, 0xde, 0xad, 0xbe, 0xef, // OID
0x05, 0x00 // NULL
};
Input input;
ASSERT_EQ(Success, input.Init(DER_ALGORITHM_IDENTIFIER_NULL_PARAMS,
sizeof DER_ALGORITHM_IDENTIFIER_NULL_PARAMS));
uint16_t length;
ASSERT_EQ(Success, ExpectTagAndGetLength(input, SEQUENCE, length));
Input nested;
ASSERT_EQ(Success, input.Skip(length, nested));
const uint8_t expectedAlgorithmID[] = {
0xde, 0xad, 0xbe, 0xef
};
SECAlgorithmID algorithmID;
ASSERT_EQ(Success, AlgorithmIdentifier(nested, algorithmID));
ASSERT_EQ(sizeof expectedAlgorithmID, algorithmID.algorithm.len);
ASSERT_TRUE(memcmp(algorithmID.algorithm.data, expectedAlgorithmID,
sizeof expectedAlgorithmID) == 0);
ASSERT_EQ((size_t) 0, algorithmID.parameters.len);
ASSERT_EQ(NULL, algorithmID.parameters.data);
}
TEST_F(pkixder_pki_types_tests, CertificateSerialNumber)
{
const uint8_t DER_CERT_SERIAL[] = {
0x02, // INTEGER
8, // length
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
};
Input input;
ASSERT_EQ(Success, input.Init(DER_CERT_SERIAL, sizeof DER_CERT_SERIAL));
SECItem item;
ASSERT_EQ(Success, CertificateSerialNumber(input, item));
ASSERT_EQ(sizeof DER_CERT_SERIAL - 2, item.len);
ASSERT_TRUE(memcmp(item.data, DER_CERT_SERIAL + 2,
sizeof DER_CERT_SERIAL - 2) == 0);
}
TEST_F(pkixder_pki_types_tests, CertificateSerialNumberLongest)
{
const uint8_t DER_CERT_SERIAL_LONGEST[] = {
0x02, // INTEGER
20, // length
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
};
Input input;
ASSERT_EQ(Success, input.Init(DER_CERT_SERIAL_LONGEST,
sizeof DER_CERT_SERIAL_LONGEST));
SECItem item;
ASSERT_EQ(Success, CertificateSerialNumber(input, item));
ASSERT_EQ(sizeof DER_CERT_SERIAL_LONGEST - 2, item.len);
ASSERT_TRUE(memcmp(item.data, DER_CERT_SERIAL_LONGEST + 2,
sizeof DER_CERT_SERIAL_LONGEST - 2) == 0);
}
TEST_F(pkixder_pki_types_tests, CertificateSerialNumberCrazyLong)
{
const uint8_t DER_CERT_SERIAL_CRAZY_LONG[] = {
0x02, // INTEGER
32, // length
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
};
Input input;
ASSERT_EQ(Success, input.Init(DER_CERT_SERIAL_CRAZY_LONG,
sizeof DER_CERT_SERIAL_CRAZY_LONG));
SECItem item;
ASSERT_EQ(Success, CertificateSerialNumber(input, item));
}
TEST_F(pkixder_pki_types_tests, CertificateSerialNumberZeroLength)
{
const uint8_t DER_CERT_SERIAL_ZERO_LENGTH[] = {
0x02, // INTEGER
0x00 // length
};
Input input;
ASSERT_EQ(Success, input.Init(DER_CERT_SERIAL_ZERO_LENGTH,
sizeof DER_CERT_SERIAL_ZERO_LENGTH));
SECItem item;
ASSERT_EQ(Failure, CertificateSerialNumber(input, item));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_pki_types_tests, OptionalVersionV1)
{
const uint8_t DER_OPTIONAL_VERSION_V1[] = {
0xa0, 0x03, // context specific 0
0x02, 0x01, 0x00 // INTEGER(0)
};
Input input;
ASSERT_EQ(Success, input.Init(DER_OPTIONAL_VERSION_V1,
sizeof DER_OPTIONAL_VERSION_V1));
uint8_t version = 99;
// TODO(bug 982783): An explicit value of 1 is not allowed, because it is not
// the shortest possible encoding!
ASSERT_EQ(Success, OptionalVersion(input, version));
ASSERT_EQ(v1, version);
}
TEST_F(pkixder_pki_types_tests, OptionalVersionV2)
{
const uint8_t DER_OPTIONAL_VERSION_V2[] = {
0xa0, 0x03, // context specific 0
0x02, 0x01, 0x01 // INTEGER(1)
};
Input input;
ASSERT_EQ(Success, input.Init(DER_OPTIONAL_VERSION_V2,
sizeof DER_OPTIONAL_VERSION_V2));
uint8_t version = 99;
ASSERT_EQ(Success, OptionalVersion(input, version));
ASSERT_EQ(v2, version);
}
TEST_F(pkixder_pki_types_tests, OptionalVersionV3)
{
const uint8_t DER_OPTIONAL_VERSION_V3[] = {
0xa0, 0x03, // context specific 0
0x02, 0x01, 0x02 // INTEGER(2)
};
Input input;
ASSERT_EQ(Success, input.Init(DER_OPTIONAL_VERSION_V3,
sizeof DER_OPTIONAL_VERSION_V3));
uint8_t version = 99;
ASSERT_EQ(Success, OptionalVersion(input, version));
ASSERT_EQ(v3, version);
}
TEST_F(pkixder_pki_types_tests, OptionalVersionUnknown)
{
const uint8_t DER_OPTIONAL_VERSION_INVALID[] = {
0xa0, 0x03, // context specific 0
0x02, 0x01, 0x42 // INTEGER(0x42)
};
Input input;
ASSERT_EQ(Success, input.Init(DER_OPTIONAL_VERSION_INVALID,
sizeof DER_OPTIONAL_VERSION_INVALID));
uint8_t version = 99;
ASSERT_EQ(Success, OptionalVersion(input, version));
ASSERT_EQ(0x42, version);
}
TEST_F(pkixder_pki_types_tests, OptionalVersionInvalidTooLong)
{
const uint8_t DER_OPTIONAL_VERSION_INVALID_TOO_LONG[] = {
0xa0, 0x03, // context specific 0
0x02, 0x02, 0x12, 0x34 // INTEGER(0x1234)
};
Input input;
ASSERT_EQ(Success, input.Init(DER_OPTIONAL_VERSION_INVALID_TOO_LONG,
sizeof DER_OPTIONAL_VERSION_INVALID_TOO_LONG));
uint8_t version = 99;
ASSERT_EQ(Failure, OptionalVersion(input, version));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_pki_types_tests, OptionalVersionMissing)
{
const uint8_t DER_OPTIONAL_VERSION_MISSING[] = {
0x02, 0x11, 0x22 // INTEGER
};
Input input;
ASSERT_EQ(Success, input.Init(DER_OPTIONAL_VERSION_MISSING,
sizeof DER_OPTIONAL_VERSION_MISSING));
uint8_t version = 99;
ASSERT_EQ(Success, OptionalVersion(input, version));
ASSERT_EQ(v1, version);
}
} // unnamed namespace

View File

@ -0,0 +1,425 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* Copyright 2013 Mozilla Foundation
*
* 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 <functional>
#include <vector>
#include <gtest/gtest.h>
#include "pkix/bind.h"
#include "pkixder.h"
using namespace mozilla::pkix::der;
namespace {
class pkixder_universal_types_tests : public ::testing::Test
{
protected:
virtual void SetUp()
{
PR_SetError(0, 0);
}
};
TEST_F(pkixder_universal_types_tests, BooleanTrue01)
{
const uint8_t DER_BOOLEAN_TRUE_01[] = {
0x01, // INTEGER
0x01, // length
0x01 // invalid
};
Input input;
ASSERT_EQ(Success,
input.Init(DER_BOOLEAN_TRUE_01, sizeof DER_BOOLEAN_TRUE_01));
bool value = false;
ASSERT_EQ(Failure, Boolean(input, value));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_universal_types_tests, BooleanTrue42)
{
const uint8_t DER_BOOLEAN_TRUE_42[] = {
0x01, // INTEGER
0x01, // length
0x42 // invalid
};
Input input;
ASSERT_EQ(Success,
input.Init(DER_BOOLEAN_TRUE_42, sizeof DER_BOOLEAN_TRUE_42));
bool value = false;
ASSERT_EQ(Failure, Boolean(input, value));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_universal_types_tests, BooleanTrueFF)
{
const uint8_t DER_BOOLEAN_TRUE_FF[] = {
0x01, // INTEGER
0x01, // length
0xff // true
};
Input input;
ASSERT_EQ(Success,
input.Init(DER_BOOLEAN_TRUE_FF, sizeof DER_BOOLEAN_TRUE_FF));
bool value = false;
ASSERT_EQ(Success, Boolean(input, value));
ASSERT_EQ(true, value);
}
TEST_F(pkixder_universal_types_tests, BooleanFalse)
{
const uint8_t DER_BOOLEAN_FALSE[] = {
0x01, // INTEGER
0x01, // length
0x00 // false
};
Input input;
ASSERT_EQ(Success, input.Init(DER_BOOLEAN_FALSE, sizeof DER_BOOLEAN_FALSE));
bool value = true;
ASSERT_EQ(Success, Boolean(input, value));
ASSERT_EQ(false, value);
}
TEST_F(pkixder_universal_types_tests, BooleanInvalidLength)
{
const uint8_t DER_BOOLEAN_INVALID_LENGTH[] = {
0x01, // INTEGER
0x02, // length
0x42, 0x42 // invalid
};
Input input;
ASSERT_EQ(Success, input.Init(DER_BOOLEAN_INVALID_LENGTH,
sizeof DER_BOOLEAN_INVALID_LENGTH));
bool value = true;
ASSERT_EQ(Failure, Boolean(input, value));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_universal_types_tests, BooleanInvalidZeroLength)
{
const uint8_t DER_BOOLEAN_INVALID_ZERO_LENGTH[] = {
0x01, // INTEGER
0x00 // length
};
Input input;
ASSERT_EQ(Success, input.Init(DER_BOOLEAN_INVALID_ZERO_LENGTH,
sizeof DER_BOOLEAN_INVALID_ZERO_LENGTH));
bool value = true;
ASSERT_EQ(Failure, Boolean(input, value));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_universal_types_tests, Enumerated)
{
const uint8_t DER_ENUMERATED[] = {
0x0a, // INTEGER
0x01, // length
0x42 // value
};
Input input;
ASSERT_EQ(Success, input.Init(DER_ENUMERATED, sizeof DER_ENUMERATED));
uint8_t value = 0;
ASSERT_EQ(Success, Enumerated(input, value));
ASSERT_EQ(0x42, value);
}
TEST_F(pkixder_universal_types_tests, EnumeratedNotShortestPossibleDER)
{
const uint8_t DER_ENUMERATED[] = {
0x0a, // INTEGER
0x02, // length
0x00, 0x01 // value
};
Input input;
ASSERT_EQ(Success, input.Init(DER_ENUMERATED, sizeof DER_ENUMERATED));
uint8_t value = 0;
ASSERT_EQ(Failure, Enumerated(input, 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, // INTEGER
0x02, // length
0x12, 0x34 // value
};
Input input;
ASSERT_EQ(Success, input.Init(DER_ENUMERATED_INVALID_LENGTH,
sizeof DER_ENUMERATED_INVALID_LENGTH));
uint8_t value = 0;
ASSERT_EQ(Failure, Enumerated(input, value));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_universal_types_tests, EnumeratedInvalidZeroLength)
{
const uint8_t DER_ENUMERATED_INVALID_ZERO_LENGTH[] = {
0x0a, // INTEGER
0x00 // length
};
Input input;
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.
TEST_F(pkixder_universal_types_tests, GeneralizedTimeOffset)
{
const uint8_t DER_GENERALIZED_TIME_OFFSET[] = {
0x18,
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,
'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);
PRTime value = 0;
Result rv2 = GeneralizedTime(input, value);
ASSERT_EQ(Success, rv2);
ASSERT_EQ(673548340000000, value);
}
TEST_F(pkixder_universal_types_tests, GeneralizedTimeInvalidZeroLength)
{
const uint8_t DER_GENERALIZED_TIME_INVALID_ZERO_LENGTH[] = {
0x18,
0x00
};
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());
}
TEST_F(pkixder_universal_types_tests, Integer)
{
const uint8_t DER_INTEGUR[] = {
0x02, // INTEGER
0x04, // length
0x11, 0x22, 0x33, 0x44 // 0x11223344
};
Input input;
ASSERT_EQ(Success, input.Init(DER_INTEGUR, sizeof DER_INTEGUR));
const uint8_t expectedItemData[] = { 0x11, 0x22, 0x33, 0x44 };
SECItem item;
memset(&item, 0x00, sizeof item);
ASSERT_EQ(Success, Integer(input, item));
ASSERT_EQ(siBuffer, item.type);
ASSERT_EQ((size_t) 4, item.len);
ASSERT_TRUE(item.data);
ASSERT_EQ(0, memcmp(item.data, expectedItemData, sizeof expectedItemData));
}
TEST_F(pkixder_universal_types_tests, OneByte)
{
const uint8_t DER_INTEGUR[] = {
0x02, // INTEGER
0x01, // length
0x11 // 0x11
};
Input input;
ASSERT_EQ(Success, input.Init(DER_INTEGUR, sizeof DER_INTEGUR));
const uint8_t expectedItemData[] = { 0x11 };
SECItem item;
memset(&item, 0x00, sizeof item);
ASSERT_EQ(Success, Integer(input, item));
ASSERT_EQ(siBuffer, item.type);
ASSERT_EQ((size_t) 1, item.len);
ASSERT_TRUE(item.data);
ASSERT_EQ(0, memcmp(item.data, expectedItemData, sizeof expectedItemData));
}
TEST_F(pkixder_universal_types_tests, IntegerTruncated)
{
const uint8_t DER_INTEGER_TRUNCATED[] = {
0x02, // INTEGER
0x04, // length
0x11, 0x22 // 0x1122
// MISSING DATA HERE
};
Input input;
ASSERT_EQ(Success,
input.Init(DER_INTEGER_TRUNCATED, sizeof DER_INTEGER_TRUNCATED));
SECItem item;
memset(&item, 0x00, sizeof item);
ASSERT_EQ(Failure, Integer(input, item));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
ASSERT_EQ(0, item.type);
ASSERT_EQ(0, item.len);
}
TEST_F(pkixder_universal_types_tests, IntegerZeroLength)
{
const uint8_t DER_INTEGER_ZERO_LENGTH[] = {
0x02, // INTEGER
0x00 // length
};
Input input;
ASSERT_EQ(Success, input.Init(DER_INTEGER_ZERO_LENGTH,
sizeof DER_INTEGER_ZERO_LENGTH));
SECItem item;
ASSERT_EQ(Failure, Integer(input, item));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
}
TEST_F(pkixder_universal_types_tests, IntegerOverlyLong1)
{
const uint8_t DER_INTEGER_OVERLY_LONG1[] = {
0x02, // INTEGER
0x02, // length
0x00, 0x01 //
};
Input input;
ASSERT_EQ(Success, input.Init(DER_INTEGER_OVERLY_LONG1,
sizeof DER_INTEGER_OVERLY_LONG1));
SECItem item;
ASSERT_EQ(Failure, Integer(input, item));
}
TEST_F(pkixder_universal_types_tests, IntegerOverlyLong2)
{
const uint8_t DER_INTEGER_OVERLY_LONG2[] = {
0x02, // INTEGER
0x02, // length
0xff, 0x80 //
};
Input input;
ASSERT_EQ(Success, input.Init(DER_INTEGER_OVERLY_LONG2,
sizeof DER_INTEGER_OVERLY_LONG2));
SECItem item;
ASSERT_EQ(Failure, Integer(input, item));
}
TEST_F(pkixder_universal_types_tests, Null)
{
const uint8_t DER_NUL[] = {
0x05,
0x00
};
Input input;
ASSERT_EQ(Success, input.Init(DER_NUL, sizeof DER_NUL));
ASSERT_EQ(Success, Null(input));
}
TEST_F(pkixder_universal_types_tests, NullWithBadLength)
{
const uint8_t DER_NULL_BAD_LENGTH[] = {
0x05,
0x01,
0x00
};
Input input;
ASSERT_EQ(Success,
input.Init(DER_NULL_BAD_LENGTH, sizeof DER_NULL_BAD_LENGTH));
ASSERT_EQ(Failure, Null(input));
}
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;
ASSERT_EQ(Success, input.Init(DER_VALID_OID, sizeof DER_VALID_OID));
const uint8_t expectedOID[] = {
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
};
ASSERT_EQ(Success, OID(input, expectedOID));
}
} // unnamed namespace