Add FPDFSignatureObj_GetSubFilter() API

This follows the same pattern as FPDFSignatureObj_GetByteRange(), so the
client has to call this function twice, but allocation of the buffer
happens outside pdfium.

The buffer format is documented to be NUL-terminated ASCII, since the
PDF reference gives examples on how the SubFilter should be named, and
all of them are ASCII, so probably UTF-8 or UTF-16 would be an overkill
here.

Change-Id: I3a9b360f219578745ea501cbdfb39a117ca5f2bc
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/71970
Commit-Queue: Miklos V <vmiklos@collabora.co.uk>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/fpdf_signature_embeddertest.cpp b/fpdfsdk/fpdf_signature_embeddertest.cpp
index 8a93916..5df611a 100644
--- a/fpdfsdk/fpdf_signature_embeddertest.cpp
+++ b/fpdfsdk/fpdf_signature_embeddertest.cpp
@@ -92,3 +92,39 @@
   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_NE(nullptr, 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<char> 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_NE(nullptr, signature);
+
+  // FPDFSignatureObj_GetSubFilter() negative testing: no SubFilter
+  ASSERT_EQ(0U, FPDFSignatureObj_GetSubFilter(signature, nullptr, 0));
+}