// Copyright 2020 The PDFium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include "public/fpdf_signature.h" #include "testing/embedder_test.h" #include "testing/fx_string_testhelpers.h" class FPDFSignatureEmbedderTest : public EmbedderTest {}; TEST_F(FPDFSignatureEmbedderTest, GetSignatureCount) { ASSERT_TRUE(OpenDocument("two_signatures.pdf")); EXPECT_EQ(2, FPDF_GetSignatureCount(document())); } TEST_F(FPDFSignatureEmbedderTest, GetSignatureCountZero) { ASSERT_TRUE(OpenDocument("hello_world.pdf")); EXPECT_EQ(0, FPDF_GetSignatureCount(document())); // Provide no document. EXPECT_EQ(-1, FPDF_GetSignatureCount(nullptr)); } TEST_F(FPDFSignatureEmbedderTest, GetSignatureObject) { ASSERT_TRUE(OpenDocument("two_signatures.pdf")); // Different, non-null signature objects are returned. FPDF_SIGNATURE signature1 = FPDF_GetSignatureObject(document(), 0); EXPECT_TRUE(signature1); FPDF_SIGNATURE signature2 = FPDF_GetSignatureObject(document(), 1); EXPECT_TRUE(signature2); EXPECT_NE(signature1, signature2); // Out of bounds. EXPECT_FALSE(FPDF_GetSignatureObject(document(), -1)); EXPECT_FALSE(FPDF_GetSignatureObject(document(), 2)); // Provide no document. EXPECT_FALSE(FPDF_GetSignatureObject(nullptr, 0)); } TEST_F(FPDFSignatureEmbedderTest, GetContents) { ASSERT_TRUE(OpenDocument("two_signatures.pdf")); FPDF_SIGNATURE signature = FPDF_GetSignatureObject(document(), 0); EXPECT_TRUE(signature); // FPDFSignatureObj_GetContents() positive testing. unsigned long size = FPDFSignatureObj_GetContents(signature, nullptr, 0); const uint8_t kExpectedContents[] = {0x30, 0x80, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01}; ASSERT_EQ(sizeof(kExpectedContents), size); std::vector contents(size); ASSERT_EQ(size, FPDFSignatureObj_GetContents(signature, contents.data(), size)); ASSERT_EQ(0, memcmp(kExpectedContents, contents.data(), size)); // FPDFSignatureObj_GetContents() negative testing. ASSERT_EQ(0U, FPDFSignatureObj_GetContents(nullptr, nullptr, 0)); contents.resize(2); contents[0] = 'x'; contents[1] = '\0'; size = FPDFSignatureObj_GetContents(signature, contents.data(), contents.size()); ASSERT_EQ(sizeof(kExpectedContents), size); EXPECT_EQ('x', contents[0]); EXPECT_EQ('\0', contents[1]); } TEST_F(FPDFSignatureEmbedderTest, GetByteRange) { ASSERT_TRUE(OpenDocument("two_signatures.pdf")); FPDF_SIGNATURE signature = FPDF_GetSignatureObject(document(), 0); EXPECT_TRUE(signature); // FPDFSignatureObj_GetByteRange() positive testing. unsigned long size = FPDFSignatureObj_GetByteRange(signature, nullptr, 0); const std::vector kExpectedByteRange{0, 10, 30, 10}; ASSERT_EQ(kExpectedByteRange.size(), size); std::vector byte_range(size); ASSERT_EQ(size, FPDFSignatureObj_GetByteRange(signature, byte_range.data(), size)); ASSERT_EQ(kExpectedByteRange, byte_range); // FPDFSignatureObj_GetByteRange() negative testing. ASSERT_EQ(0U, FPDFSignatureObj_GetByteRange(nullptr, nullptr, 0)); byte_range.resize(2); byte_range[0] = 0; byte_range[1] = 1; size = FPDFSignatureObj_GetByteRange(signature, byte_range.data(), byte_range.size()); ASSERT_EQ(kExpectedByteRange.size(), size); EXPECT_EQ(0, byte_range[0]); EXPECT_EQ(1, byte_range[1]); } TEST_F(FPDFSignatureEmbedderTest, GetSubFilter) { ASSERT_TRUE(OpenDocument("two_signatures.pdf")); FPDF_SIGNATURE signature = FPDF_GetSignatureObject(document(), 0); EXPECT_TRUE(signature); // FPDFSignatureObj_GetSubFilter() positive testing. unsigned long size = FPDFSignatureObj_GetSubFilter(signature, nullptr, 0); const char kExpectedSubFilter[] = "ETSI.CAdES.detached"; ASSERT_EQ(sizeof(kExpectedSubFilter), size); std::vector sub_filter(size); ASSERT_EQ(size, FPDFSignatureObj_GetSubFilter(signature, sub_filter.data(), size)); ASSERT_EQ(0, memcmp(kExpectedSubFilter, sub_filter.data(), size)); // FPDFSignatureObj_GetSubFilter() negative testing. ASSERT_EQ(0U, FPDFSignatureObj_GetSubFilter(nullptr, nullptr, 0)); sub_filter.resize(2); sub_filter[0] = 'x'; sub_filter[1] = '\0'; size = FPDFSignatureObj_GetSubFilter(signature, sub_filter.data(), sub_filter.size()); ASSERT_EQ(sizeof(kExpectedSubFilter), size); EXPECT_EQ('x', sub_filter[0]); EXPECT_EQ('\0', sub_filter[1]); } TEST_F(FPDFSignatureEmbedderTest, GetSubFilterNoKeyExists) { ASSERT_TRUE(OpenDocument("signature_no_sub_filter.pdf")); FPDF_SIGNATURE signature = FPDF_GetSignatureObject(document(), 0); EXPECT_TRUE(signature); // FPDFSignatureObj_GetSubFilter() negative testing: no SubFilter ASSERT_EQ(0U, FPDFSignatureObj_GetSubFilter(signature, nullptr, 0)); } TEST_F(FPDFSignatureEmbedderTest, GetReason) { ASSERT_TRUE(OpenDocument("signature_reason.pdf")); FPDF_SIGNATURE signature = FPDF_GetSignatureObject(document(), 0); EXPECT_TRUE(signature); // FPDFSignatureObj_GetReason() positive testing. constexpr char kReason[] = "test reason"; // Return value includes the terminating NUL that is provided. constexpr unsigned long kReasonUTF16Size = std::size(kReason) * 2; constexpr wchar_t kReasonWide[] = L"test reason"; unsigned long size = FPDFSignatureObj_GetReason(signature, nullptr, 0); ASSERT_EQ(kReasonUTF16Size, size); std::vector buffer(size); ASSERT_EQ(size, FPDFSignatureObj_GetReason(signature, buffer.data(), size)); ASSERT_EQ(kReasonWide, GetPlatformWString(buffer.data())); // FPDFSignatureObj_GetReason() negative testing. ASSERT_EQ(0U, FPDFSignatureObj_GetReason(nullptr, nullptr, 0)); // Buffer is too small, ensure it's not modified. buffer.resize(2); buffer[0] = 'x'; buffer[1] = '\0'; size = FPDFSignatureObj_GetReason(signature, buffer.data(), buffer.size()); ASSERT_EQ(kReasonUTF16Size, size); EXPECT_EQ('x', buffer[0]); EXPECT_EQ('\0', buffer[1]); } TEST_F(FPDFSignatureEmbedderTest, GetTime) { ASSERT_TRUE(OpenDocument("two_signatures.pdf")); FPDF_SIGNATURE signature = FPDF_GetSignatureObject(document(), 0); EXPECT_TRUE(signature); // FPDFSignatureObj_GetTime() positive testing. unsigned long size = FPDFSignatureObj_GetTime(signature, nullptr, 0); const char kExpectedTime[] = "D:20200624093114+02'00'"; ASSERT_EQ(sizeof(kExpectedTime), size); std::vector time_buffer(size); ASSERT_EQ(size, FPDFSignatureObj_GetTime(signature, time_buffer.data(), size)); ASSERT_EQ(0, memcmp(kExpectedTime, time_buffer.data(), size)); // FPDFSignatureObj_GetTime() negative testing. ASSERT_EQ(0U, FPDFSignatureObj_GetTime(nullptr, nullptr, 0)); time_buffer.resize(2); time_buffer[0] = 'x'; time_buffer[1] = '\0'; size = FPDFSignatureObj_GetTime(signature, time_buffer.data(), time_buffer.size()); ASSERT_EQ(sizeof(kExpectedTime), size); EXPECT_EQ('x', time_buffer[0]); EXPECT_EQ('\0', time_buffer[1]); } TEST_F(FPDFSignatureEmbedderTest, GetDocMDPPermission) { ASSERT_TRUE(OpenDocument("docmdp.pdf")); FPDF_SIGNATURE signature = FPDF_GetSignatureObject(document(), 0); ASSERT_NE(nullptr, signature); // FPDFSignatureObj_GetDocMDPPermission() positive testing. unsigned int permission = FPDFSignatureObj_GetDocMDPPermission(signature); EXPECT_EQ(1U, permission); // FPDFSignatureObj_GetDocMDPPermission() negative testing. EXPECT_EQ(0U, FPDFSignatureObj_GetDocMDPPermission(nullptr)); }