diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2020-11-11 21:09:06 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2020-11-12 09:02:25 +0100 |
commit | 9e0ff8d1929b9925473f9efc54fd7bd0c90611c2 (patch) | |
tree | 5158e8547957be398b1056d5b1dac6938e4cfa61 /external | |
parent | 941b5a0bb597285737b4796106974468ac357b17 (diff) |
xmlsecurity: prepare to verify signatures using pdfium
All the needed API is already in the version we bundle, except one. And
also we'll need direct access to the underling pdfium document, for now.
Change-Id: Ib5c87c95072401b1a6ca0151177d70b4bcd8c46d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105610
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'external')
-rw-r--r-- | external/pdfium/SignatureGetDocMDPPermission.patch.1 | 345 | ||||
-rw-r--r-- | external/pdfium/UnpackedTarball_pdfium.mk | 1 |
2 files changed, 346 insertions, 0 deletions
diff --git a/external/pdfium/SignatureGetDocMDPPermission.patch.1 b/external/pdfium/SignatureGetDocMDPPermission.patch.1 new file mode 100644 index 000000000000..0304ad0999ce --- /dev/null +++ b/external/pdfium/SignatureGetDocMDPPermission.patch.1 @@ -0,0 +1,345 @@ +From f63c9650bca285932fb4dced804f9eec7e40b5ff Mon Sep 17 00:00:00 2001 +From: Miklos Vajna <vmiklos@collabora.co.uk> +Date: Tue, 3 Nov 2020 16:32:12 +0000 +Subject: [PATCH] Add FPDFSignatureObj_GetDocMDPPermission() + +A document is OK to not contain any explicit markup for this, in which +case 0 is returned. If a permission parameter is found, then the +returned level of 1, 2 or 3 controls if no incremental updates are +allowed (1) or incremental updates are OK, but annotations are not +allowed (2) or even annotations are allowed (3). + +Note how there is a difference between omitting just the /P key +(implicitly means 2) and omitting the more of this markup, which will +return 0. + +This API is meant to be used in combination with the +FPDF_GetTrailerEnds() API, which allows detecting additional incremental +updates after a signature. For example, if a comment is added after +signing, then Permission=1 would result in an invalid signature, while +Permission=3 just results in a partial signature. + +Change-Id: I911e9ddaff3a687729e7fe610c013b2ce3283d36 +Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/75910 +Commit-Queue: Tom Sepez <tsepez@chromium.org> +Reviewed-by: Tom Sepez <tsepez@chromium.org> +--- + fpdfsdk/fpdf_signature.cpp | 41 ++++++++++ + fpdfsdk/fpdf_signature_embeddertest.cpp | 13 +++ + fpdfsdk/fpdf_view_c_api_test.c | 1 + + public/fpdf_signature.h | 11 +++ + testing/resources/docmdp.in | 88 ++++++++++++++++++++ + testing/resources/docmdp.pdf | 102 ++++++++++++++++++++++++ + 6 files changed, 256 insertions(+) + create mode 100644 testing/resources/docmdp.in + create mode 100644 testing/resources/docmdp.pdf + +diff --git a/fpdfsdk/fpdf_signature.cpp b/fpdfsdk/fpdf_signature.cpp +index b438b8f6a..975c2522e 100644 +--- a/fpdfsdk/fpdf_signature.cpp ++++ b/fpdfsdk/fpdf_signature.cpp +@@ -157,3 +157,44 @@ FPDFSignatureObj_GetTime(FPDF_SIGNATURE signature, + + return NulTerminateMaybeCopyAndReturnLength(obj->GetString(), buffer, length); + } ++ ++FPDF_EXPORT unsigned int FPDF_CALLCONV ++FPDFSignatureObj_GetDocMDPPermission(FPDF_SIGNATURE signature) { ++ int permission = 0; ++ CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature); ++ if (!signature_dict) ++ return permission; ++ ++ CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V"); ++ if (!value_dict) ++ return permission; ++ ++ CPDF_Array* references = value_dict->GetArrayFor("Reference"); ++ if (!references) ++ return permission; ++ ++ CPDF_ArrayLocker locker(references); ++ for (auto& reference : locker) { ++ CPDF_Dictionary* reference_dict = reference->GetDict(); ++ if (!reference_dict) ++ continue; ++ ++ ByteString transform_method = reference_dict->GetNameFor("TransformMethod"); ++ if (transform_method != "DocMDP") ++ continue; ++ ++ CPDF_Dictionary* transform_params = ++ reference_dict->GetDictFor("TransformParams"); ++ if (!transform_params) ++ continue; ++ ++ // Valid values are 1, 2 and 3; 2 is the default. ++ permission = transform_params->GetIntegerFor("P", 2); ++ if (permission < 1 || permission > 3) ++ permission = 0; ++ ++ return permission; ++ } ++ ++ return permission; ++} +diff --git a/fpdfsdk/fpdf_signature_embeddertest.cpp b/fpdfsdk/fpdf_signature_embeddertest.cpp +index d2fd9c663..e91d9c221 100644 +--- a/fpdfsdk/fpdf_signature_embeddertest.cpp ++++ b/fpdfsdk/fpdf_signature_embeddertest.cpp +@@ -187,3 +187,16 @@ TEST_F(FPDFSignatureEmbedderTest, GetTime) { + 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)); ++} +diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c +index 7708cbab9..1142725d6 100644 +--- a/fpdfsdk/fpdf_view_c_api_test.c ++++ b/fpdfsdk/fpdf_view_c_api_test.c +@@ -320,6 +320,7 @@ int CheckPDFiumCApi() { + // fpdf_signature.h + CHK(FPDFSignatureObj_GetByteRange); + CHK(FPDFSignatureObj_GetContents); ++ CHK(FPDFSignatureObj_GetDocMDPPermission); + CHK(FPDFSignatureObj_GetReason); + CHK(FPDFSignatureObj_GetSubFilter); + CHK(FPDFSignatureObj_GetTime); +diff --git a/public/fpdf_signature.h b/public/fpdf_signature.h +index f20d9add3..702b67bae 100644 +--- a/public/fpdf_signature.h ++++ b/public/fpdf_signature.h +@@ -137,6 +137,17 @@ FPDFSignatureObj_GetTime(FPDF_SIGNATURE signature, + char* buffer, + unsigned long length); + ++// Experimental API. ++// Function: FPDFSignatureObj_GetDocMDPPermission ++// Get the DocMDP permission of a signature object. ++// Parameters: ++// signature - Handle to the signature object. Returned by ++// FPDF_GetSignatureObject(). ++// Return value: ++// Returns the permission (1, 2 or 3) on success, 0 on error. ++FPDF_EXPORT unsigned int FPDF_CALLCONV ++FPDFSignatureObj_GetDocMDPPermission(FPDF_SIGNATURE signature); ++ + #ifdef __cplusplus + } // extern "C" + #endif // __cplusplus +diff --git a/testing/resources/docmdp.in b/testing/resources/docmdp.in +new file mode 100644 +index 000000000..a8fe28373 +--- /dev/null ++++ b/testing/resources/docmdp.in +@@ -0,0 +1,88 @@ ++{{header}} ++{{object 1 0}} << ++ /Type /Catalog ++ /Pages 2 0 R ++ /AcroForm << ++ /Fields [7 0 R] ++ /SigFlags 3 ++ >> ++>> ++endobj ++endobj ++{{object 2 0}} << ++ /Type /Pages ++ /MediaBox [0 0 200 300] ++ /Count 1 ++ /Kids [3 0 R] ++>> ++endobj ++{{object 3 0}} << ++ /Type /Page ++ /Parent 2 0 R ++ /Contents 4 0 R ++ /Annots [7 0 R] ++>> ++endobj ++{{object 4 0}} << ++ {{streamlen}} ++>> ++stream ++q ++0 0 0 rg ++0 290 10 10 re B* ++10 150 50 30 re B* ++0 0 1 rg ++190 290 10 10 re B* ++70 232 50 30 re B* ++0 1 0 rg ++190 0 10 10 re B* ++130 150 50 30 re B* ++1 0 0 rg ++0 0 10 10 re B* ++70 67 50 30 re B* ++Q ++endstream ++endobj ++{{object 5 0}} << ++ /Type /Sig ++ /Reference [ ++ << ++ /Type /SigRef ++ /TransformMethod /DocMDP ++ /TransformParams << ++ /Type /TransformParams ++ /P 1 ++ /V /1.2 ++ >> ++ >> ++ ] ++>> ++endobj ++{{object 6 0}} << ++ /Type /XObject ++ /Subtype /Form ++ /BBox [0 0 0 0] ++ /Length 0 ++>> ++stream ++endstream ++endobj ++{{object 7 0}} << ++ /Type /Annot ++ /Subtype /Widget ++ /FT /Sig ++ /F 132 ++ /Rect [0 0 0 0] ++ /P 3 0 R ++ /T (Signature1) ++ /V 5 0 R ++ /DV 5 0 R ++ /AP << ++ /N 6 0 R ++ >> ++>> ++endobj ++{{xref}} ++{{trailer}} ++{{startxref}} ++%%EOF +diff --git a/testing/resources/docmdp.pdf b/testing/resources/docmdp.pdf +new file mode 100644 +index 000000000..0191a0029 +--- /dev/null ++++ b/testing/resources/docmdp.pdf +@@ -0,0 +1,102 @@ ++%PDF-1.7 ++% ++1 0 obj << ++ /Type /Catalog ++ /Pages 2 0 R ++ /AcroForm << ++ /Fields [7 0 R] ++ /SigFlags 3 ++ >> ++>> ++endobj ++endobj ++2 0 obj << ++ /Type /Pages ++ /MediaBox [0 0 200 300] ++ /Count 1 ++ /Kids [3 0 R] ++>> ++endobj ++3 0 obj << ++ /Type /Page ++ /Parent 2 0 R ++ /Contents 4 0 R ++ /Annots [7 0 R] ++>> ++endobj ++4 0 obj << ++ /Length 188 ++>> ++stream ++q ++0 0 0 rg ++0 290 10 10 re B* ++10 150 50 30 re B* ++0 0 1 rg ++190 290 10 10 re B* ++70 232 50 30 re B* ++0 1 0 rg ++190 0 10 10 re B* ++130 150 50 30 re B* ++1 0 0 rg ++0 0 10 10 re B* ++70 67 50 30 re B* ++Q ++endstream ++endobj ++5 0 obj << ++ /Type /Sig ++ /Reference [ ++ << ++ /Type /SigRef ++ /TransformMethod /DocMDP ++ /TransformParams << ++ /Type /TransformParams ++ /P 1 ++ /V /1.2 ++ >> ++ >> ++ ] ++>> ++endobj ++6 0 obj << ++ /Type /XObject ++ /Subtype /Form ++ /BBox [0 0 0 0] ++ /Length 0 ++>> ++stream ++endstream ++endobj ++7 0 obj << ++ /Type /Annot ++ /Subtype /Widget ++ /FT /Sig ++ /F 132 ++ /Rect [0 0 0 0] ++ /P 3 0 R ++ /T (Signature1) ++ /V 5 0 R ++ /DV 5 0 R ++ /AP << ++ /N 6 0 R ++ >> ++>> ++endobj ++xref ++0 8 ++0000000000 65535 f ++0000000015 00000 n ++0000000131 00000 n ++0000000220 00000 n ++0000000307 00000 n ++0000000547 00000 n ++0000000760 00000 n ++0000000862 00000 n ++trailer << ++ /Root 1 0 R ++ /Size 8 ++>> ++startxref ++1034 ++%%EOF +-- +2.26.2 + diff --git a/external/pdfium/UnpackedTarball_pdfium.mk b/external/pdfium/UnpackedTarball_pdfium.mk index 152178c2b1ca..c0cc000e40be 100644 --- a/external/pdfium/UnpackedTarball_pdfium.mk +++ b/external/pdfium/UnpackedTarball_pdfium.mk @@ -17,6 +17,7 @@ pdfium_patches += c++20-comparison.patch pdfium_patches += AnnotationInkAndVertices.patch.1 pdfium_patches += AnnotationBorderProperties.patch.1 pdfium_patches += AnnotationLineStartAndEnd.patch.1 +pdfium_patches += SignatureGetDocMDPPermission.patch.1 # Work around <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94141> "c++20 rewritten operator== # recursive call mixing friend and external operators for template class" in GCC with |