summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gardiner <paul.gardiner@artifex.com>2017-12-22 15:12:31 +0000
committerPaul Gardiner <paul.gardiner@artifex.com>2018-02-02 12:38:36 +0000
commit0b04079f5057ba6c7726bd14b61abed9fde1957a (patch)
tree72893a36a9b86490566c9469071724a52b4060d9
parent9b6b7ac94658d65204fab0146907ac8c6af287bb (diff)
downloadmupdf-0b04079f5057ba6c7726bd14b61abed9fde1957a.tar.xz
Signature support: decouple mupdf from the pkcs7 implementation
The mupdf build included an implimentation of the pkcs7 functions that are needed for signing documents and verifying signatures, the implementation being either an openssl-based one, or a stub that returned errors. This commit removes the pkcs7 functions from the main mupdf library. For the sake of verification, there wasn't really a need for the pkcs7 functions to be part of mupdf. It was only the checking function that used them. The checking function is now provided as a helper, outside of the main build. The openssl-based pkcs7 functions area also supplied as a helper. Users wishing to verify signatures can either use the checking function directly, or use the source on which to base their own. Document signing requires more integration between mupdf and pkcs7 because part of the process is performed at time of signing and part when saving the document. Mupdf already had a pdf_pkcs7_signer object that kept information between the two phases. That object has now been extended to include the pkcs7 functions involved in signing, and the signing function now requires such an object, rather than a file path to a certificate. The openssl-based pkcs7 helper provides a function that, given the path to a certificate, will return a pdf_pkcs7_signer object. The intention is that different implementations can be produced for different platforms, based on cryptographic routines built into the operationg system. In each case, for the sake of document signing, the routines would be wrapped up as a pdf_pkcs7_signer object.
-rw-r--r--Makefile26
-rw-r--r--include/mupdf/helpers/pkcs7-check.h12
-rw-r--r--include/mupdf/helpers/pkcs7-openssl.h24
-rw-r--r--include/mupdf/pdf.h2
-rw-r--r--include/mupdf/pdf/crypt.h7
-rw-r--r--include/mupdf/pdf/document.h47
-rw-r--r--include/mupdf/pdf/field.h1
-rw-r--r--include/mupdf/pdf/pdf-pkcs7.h56
-rw-r--r--platform/win32/libmupdf.vcproj8
-rw-r--r--platform/win32/mupdf.vcproj308
-rw-r--r--platform/x11/pdfapp.c5
-rw-r--r--source/helpers/pkcs7/pkcs7-check.c128
-rw-r--r--source/helpers/pkcs7/pkcs7-openssl.c (renamed from source/pdf/pdf-pkcs7.c)318
-rw-r--r--source/pdf/pdf-signature.c136
-rw-r--r--source/pdf/pdf-write.c2
-rw-r--r--source/pdf/pdf-xref.c4
-rw-r--r--source/tools/pdfsign.c5
17 files changed, 699 insertions, 390 deletions
diff --git a/Makefile b/Makefile
index 3959ccf4..acf559fe 100644
--- a/Makefile
+++ b/Makefile
@@ -53,6 +53,7 @@ ALL_DIR += $(OUT)/source/gprf
ALL_DIR += $(OUT)/source/tools
ALL_DIR += $(OUT)/source/helpers
ALL_DIR += $(OUT)/source/helpers/mu-threads
+ALL_DIR += $(OUT)/source/helpers/pkcs7
ALL_DIR += $(OUT)/platform/x11
ALL_DIR += $(OUT)/platform/x11/curl
ALL_DIR += $(OUT)/platform/gl
@@ -93,9 +94,12 @@ $(OUT)/%.a :
$(OUT)/%.exe: $(OUT)/%.o | $(ALL_DIR)
$(LINK_CMD)
-$(OUT)/source/helpers/%.o : source/helpers/%.c | $(ALL_DIR)
+$(OUT)/source/helpers/mu-threads/%.o : source/helpers/mu-threads/%.c | $(ALL_DIR)
$(CC_CMD) $(THREADING_CFLAGS)
+$(OUT)/source/helpers/pkcs7/%.o : source/helpers/pkcs7/%.c | $(ALL_DIR)
+ $(CC_CMD)
+
$(OUT)/source/tools/%.o : source/tools/%.c | $(ALL_DIR)
$(CC_CMD) $(THREADING_CFLAGS)
@@ -127,6 +131,7 @@ $(OUT)/%.o : %.cpp | $(ALL_DIR)
FITZ_HDR := include/mupdf/fitz.h $(wildcard include/mupdf/fitz/*.h)
PDF_HDR := include/mupdf/pdf.h $(wildcard include/mupdf/pdf/*.h)
THREAD_HDR := include/mupdf/helpers/mu-threads.h
+PKCS7_HDR := $(sort $(wildcard include/mupdf/helpers/pkcs7-*.h))
FITZ_SRC := $(sort $(wildcard source/fitz/*.c))
PDF_SRC := $(sort $(wildcard source/pdf/*.c))
@@ -136,6 +141,7 @@ CBZ_SRC := $(sort $(wildcard source/cbz/*.c))
HTML_SRC := $(sort $(wildcard source/html/*.c))
GPRF_SRC := $(sort $(wildcard source/gprf/*.c))
THREAD_SRC := $(sort $(wildcard source/helpers/mu-threads/*.c))
+PKCS7_SRC := $(sort $(wildcard source/helpers/pkcs7/*.c))
FITZ_SRC_HDR := $(wildcard source/fitz/*.h)
PDF_SRC_HDR := $(wildcard source/pdf/*.h) source/pdf/pdf-name-table.h
@@ -152,6 +158,8 @@ CBZ_OBJ := $(CBZ_SRC:%.c=$(OUT)/%.o)
HTML_OBJ := $(HTML_SRC:%.c=$(OUT)/%.o)
GPRF_OBJ := $(GPRF_SRC:%.c=$(OUT)/%.o)
THREAD_OBJ := $(THREAD_SRC:%.c=$(OUT)/%.o)
+PKCS7_OBJ := $(PKCS7_SRC:%.c=$(OUT)/%.o)
+SIGNATURE_OBJ := $(OUT)/platform/x11/pdfapp.o $(OUT)/source/tools/pdfsign.o
$(FITZ_OBJ) : $(FITZ_HDR) $(FITZ_SRC_HDR)
$(PDF_OBJ) : $(FITZ_HDR) $(PDF_HDR) $(PDF_SRC_HDR)
@@ -163,6 +171,8 @@ $(CBZ_OBJ) : $(FITZ_HDR) $(CBZ_HDR) $(CBZ_SRC_HDR)
$(HTML_OBJ) : $(FITZ_HDR) $(HTML_HDR) $(HTML_SRC_HDR)
$(GPRF_OBJ) : $(FITZ_HDR) $(GPRF_HDR) $(GPRF_SRC_HDR)
$(THREAD_OBJ) : $(THREAD_HDR)
+$(PKCS7_OBJ) : $(FITZ_HDR) $(PDF_HDR) $(PKCS7_HDR)
+$(SIGNATURE_OBJ) : $(PKCS7_HDR)
# --- Generated PDF name tables ---
@@ -315,6 +325,9 @@ generate: $(JAVASCRIPT_GEN)
MUPDF_LIB = $(OUT)/libmupdf.a
THIRD_LIB = $(OUT)/libmupdfthird.a
THREAD_LIB = $(OUT)/libmuthreads.a
+ifeq "$(HAVE_LIBCRYPTO)" "yes"
+PKCS7_LIB = $(OUT)/libmupkcs7.a
+endif
MUPDF_OBJ := \
$(FITZ_OBJ) \
@@ -341,11 +354,12 @@ THIRD_OBJ := \
$(ZLIB_OBJ) \
$(LCMS2_OBJ)
-THREAD_OBJ := $(THREAD_OBJ)
-
$(MUPDF_LIB) : $(MUPDF_OBJ)
$(THIRD_LIB) : $(THIRD_OBJ)
$(THREAD_LIB) : $(THREAD_OBJ)
+ifeq "$(HAVE_LIBCRYPTO)" "yes"
+$(PKCS7_LIB) : $(PKCS7_OBJ)
+endif
INSTALL_LIBS := $(MUPDF_LIB) $(THIRD_LIB)
@@ -356,7 +370,7 @@ MUTOOL_SRC := source/tools/mutool.c source/tools/muconvert.c source/tools/mudraw
MUTOOL_SRC += $(sort $(wildcard source/tools/pdf*.c))
MUTOOL_OBJ := $(MUTOOL_SRC:%.c=$(OUT)/%.o)
$(MUTOOL_OBJ) : $(FITZ_HDR) $(PDF_HDR)
-$(MUTOOL_EXE) : $(MUTOOL_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(THREAD_LIB)
+$(MUTOOL_EXE) : $(MUTOOL_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(THREAD_LIB) $(PKCS7_LIB)
$(LINK_CMD) $(THREADING_LIBS)
MURASTER_EXE := $(OUT)/muraster
@@ -381,14 +395,14 @@ ifeq "$(HAVE_X11)" "yes"
MUVIEW_X11_EXE := $(OUT)/mupdf-x11
MUVIEW_X11_OBJ := $(addprefix $(OUT)/platform/x11/, x11_main.o x11_image.o pdfapp.o)
$(MUVIEW_X11_OBJ) : $(FITZ_HDR) $(PDF_HDR)
-$(MUVIEW_X11_EXE) : $(MUVIEW_X11_OBJ) $(MUPDF_LIB) $(THIRD_LIB)
+$(MUVIEW_X11_EXE) : $(MUVIEW_X11_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(PKCS7_LIB)
$(LINK_CMD) $(X11_LIBS)
ifeq "$(HAVE_CURL)" "yes"
MUVIEW_X11_CURL_EXE := $(OUT)/mupdf-x11-curl
MUVIEW_X11_CURL_OBJ := $(addprefix $(OUT)/platform/x11/curl/, x11_main.o x11_image.o pdfapp.o curl_stream.o)
$(MUVIEW_X11_CURL_OBJ) : $(FITZ_HDR) $(PDF_HDR)
-$(MUVIEW_X11_CURL_EXE) : $(MUVIEW_X11_CURL_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(CURL_LIB)
+$(MUVIEW_X11_CURL_EXE) : $(MUVIEW_X11_CURL_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(CURL_LIB) $(PKCS7_LIB)
$(LINK_CMD) $(X11_LIBS) $(CURL_LIBS) $(SYS_CURL_DEPS)
endif
endif
diff --git a/include/mupdf/helpers/pkcs7-check.h b/include/mupdf/helpers/pkcs7-check.h
new file mode 100644
index 00000000..3ff529d7
--- /dev/null
+++ b/include/mupdf/helpers/pkcs7-check.h
@@ -0,0 +1,12 @@
+#ifndef MUPDF_PKCS7_CHECK_H
+#define MUPDF_PKCS7_CHECK_H
+
+/*
+ pdf_check_signature: check a signature's certificate chain and digest
+
+ This is a helper function defined to provide compatibility with older
+ versions of mupdf
+*/
+int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, char *ebuf, int ebufsize);
+
+#endif
diff --git a/include/mupdf/helpers/pkcs7-openssl.h b/include/mupdf/helpers/pkcs7-openssl.h
new file mode 100644
index 00000000..a6268839
--- /dev/null
+++ b/include/mupdf/helpers/pkcs7-openssl.h
@@ -0,0 +1,24 @@
+#ifndef MUPDF_PKCS7_OPENSSL_H
+#define MUPDF_PKCS7_OPENSSL_H
+
+/* This an example pkcs7 implementation using openssl. These are the types of functions that you
+ * will likely need to sign documents and check signatures within documents. In particular, to
+ * sign a document, you need a function that derives a pdf_pkcs7_signer object from a certificate
+ * stored by the operating system or within a file. */
+
+/* Check a signature's digest against ranges of bytes drawn from a stream */
+SignatureError pkcs7_openssl_check_digest(fz_context *ctx, fz_stream *stm, char *sig, int sig_len);
+
+/* Check a singature's certificate is trusted */
+SignatureError pkcs7_openssl_check_certificate(char *sig, int sig_len);
+
+/* Obtain the designated name information from signature's certificate */
+pdf_pkcs7_designated_name *pkcs7_openssl_designated_name(fz_context *ctx, char *sig, int sig_len);
+
+/* Free the resources associated with designated name information */
+void pkcs7_opensll_drop_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *dn);
+
+/* Read the certificate and private key from a pfx file, holding it as an opaque structure */
+pdf_pkcs7_signer *pkcs7_openssl_read_pfx(fz_context *ctx, const char *pfile, const char *pw);
+
+#endif
diff --git a/include/mupdf/pdf.h b/include/mupdf/pdf.h
index f593e680..eab70ee9 100644
--- a/include/mupdf/pdf.h
+++ b/include/mupdf/pdf.h
@@ -31,8 +31,6 @@ extern "C" {
#include "mupdf/pdf/clean.h"
-#include "mupdf/pdf/pdf-pkcs7.h"
-
#ifdef __cplusplus
}
#endif
diff --git a/include/mupdf/pdf/crypt.h b/include/mupdf/pdf/crypt.h
index 846ed5bb..c01d3978 100644
--- a/include/mupdf/pdf/crypt.h
+++ b/include/mupdf/pdf/crypt.h
@@ -39,14 +39,9 @@ fz_stream *pdf_signature_widget_hash_bytes(fz_context *ctx, pdf_document *doc, p
int pdf_signature_widget_contents(fz_context *ctx, pdf_document *doc, pdf_widget *widget, char **contents);
/*
- pdf_check_signature: check a signature's certificate chain and digest
-*/
-int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, char *ebuf, int ebufsize);
-
-/*
pdf_sign_signature: sign a signature form field
*/
-void pdf_sign_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, const char *sigfile, const char *password);
+void pdf_sign_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, pdf_pkcs7_signer *signer);
void pdf_encrypt_data(fz_context *ctx, pdf_crypt *crypt, int num, int gen, void (*fmt_str_out)(fz_context *, void *, const unsigned char *, int), void *arg, const unsigned char *s, int n);
diff --git a/include/mupdf/pdf/document.h b/include/mupdf/pdf/document.h
index ef861145..124de254 100644
--- a/include/mupdf/pdf/document.h
+++ b/include/mupdf/pdf/document.h
@@ -535,8 +535,55 @@ void pdf_update_page(fz_context *ctx, pdf_page *page);
*/
int pdf_has_unsaved_changes(fz_context *ctx, pdf_document *doc);
+typedef enum
+{
+ SignatureError_Okay,
+ SignatureError_NoSignatures,
+ SignatureError_NoCertificate,
+ SignatureError_DocumentChanged,
+ SignatureError_SelfSigned,
+ SignatureError_SelfSignedInChain,
+ SignatureError_NotTrusted,
+ SignatureError_Unknown
+} SignatureError;
+
+typedef struct pdf_pkcs7_designated_name_s
+{
+ char *cn;
+ char *o;
+ char *ou;
+ char *email;
+ char *c;
+}
+pdf_pkcs7_designated_name;
+
+/* Object that can perform the cryptographic operation necessary for document signing */
typedef struct pdf_pkcs7_signer_s pdf_pkcs7_signer;
+/* Increment the reference count for a signer object */
+typedef pdf_pkcs7_signer *(pdf_pkcs7_keep_fn)(pdf_pkcs7_signer *signer);
+
+/* Drop a reference for a signer object */
+typedef void (pdf_pkcs7_drop_fn)(pdf_pkcs7_signer *signer);
+
+/* Obtain the designated name information from a signer object */
+typedef pdf_pkcs7_designated_name *(pdf_pkcs7_designated_name_fn)(pdf_pkcs7_signer *signer);
+
+/* Free the resources associated with previously obtained designated name information */
+typedef void (pdf_pkcs7_drop_designated_name_fn)(pdf_pkcs7_signer *signer, pdf_pkcs7_designated_name *name);
+
+/* Create a signature based on ranges of bytes drawn from a steam */
+typedef int (pdf_pkcs7_create_digest_fn)(pdf_pkcs7_signer *signer, fz_stream *in, unsigned char *digest, int *digest_len);
+
+struct pdf_pkcs7_signer_s
+{
+ pdf_pkcs7_keep_fn *keep;
+ pdf_pkcs7_drop_fn *drop;
+ pdf_pkcs7_designated_name_fn *designated_name;
+ pdf_pkcs7_drop_designated_name_fn *drop_designated_name;
+ pdf_pkcs7_create_digest_fn *create_digest;
+};
+
/* Unsaved signature fields */
typedef struct pdf_unsaved_sig_s pdf_unsaved_sig;
diff --git a/include/mupdf/pdf/field.h b/include/mupdf/pdf/field.h
index c3509938..5b25dc3f 100644
--- a/include/mupdf/pdf/field.h
+++ b/include/mupdf/pdf/field.h
@@ -51,6 +51,5 @@ char *pdf_field_name(fz_context *ctx, pdf_document *doc, pdf_obj *field);
void pdf_field_set_display(fz_context *ctx, pdf_document *doc, pdf_obj *field, int d);
pdf_obj *pdf_lookup_field(fz_context *ctx, pdf_obj *form, char *name);
void pdf_field_reset(fz_context *ctx, pdf_document *doc, pdf_obj *field);
-int pdf_signatures_supported(fz_context *ctx);
#endif
diff --git a/include/mupdf/pdf/pdf-pkcs7.h b/include/mupdf/pdf/pdf-pkcs7.h
deleted file mode 100644
index 237a036d..00000000
--- a/include/mupdf/pdf/pdf-pkcs7.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef MUPDF_PDF_PKCS7_H
-#define MUPDF_PDF_PKCS7_H
-
-typedef enum
-{
- SignatureError_Okay,
- SignatureError_NoSignatures,
- SignatureError_NoCertificate,
- SignatureError_DocumentChanged,
- SignatureError_SelfSigned,
- SignatureError_SelfSignedInChain,
- SignatureError_NotTrusted,
- SignatureError_Unknown
-} SignatureError;
-
-typedef struct pdf_pkcs7_designated_name_s
-{
- char *cn;
- char *o;
- char *ou;
- char *email;
- char *c;
-}
-pdf_pkcs7_designated_name;
-
-/* Check a signature's digest against ranges of bytes drawn from a stream */
-SignatureError pdf_pkcs7_check_digest(fz_context *ctx, fz_stream *stm, char *sig, int sig_len);
-
-/* Check a singature's certificate is trusted */
-SignatureError pdf_pkcs7_check_certificate(char *sig, int sig_len);
-
-/* Obtain the designated name information from signature's certificate */
-pdf_pkcs7_designated_name *pdf_cert_designated_name(fz_context *ctx, char *sig, int sig_len);
-
-/* Free the resources associated with designated name information */
-void pdf_pkcs7_drop_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *dn);
-
-/* Read the certificate and private key from a pfx file, holding it as an opaque structure */
-pdf_pkcs7_signer *pdf_pkcs7_read_pfx(fz_context *ctx, const char *pfile, const char *pw);
-
-/* Increment the reference count for a signer object */
-pdf_pkcs7_signer *pdf_pkcs7_keep_signer(fz_context *ctx, pdf_pkcs7_signer *signer);
-
-/* Drop a reference for a signer object */
-void pdf_pkcs7_drop_signer(fz_context *ctx, pdf_pkcs7_signer *signer);
-
-/* Obtain the designated name information from a signer object */
-pdf_pkcs7_designated_name *pdf_pkcs7_signer_designated_name(fz_context *ctx, pdf_pkcs7_signer *signer);
-
-/* Create a signature based on ranges of bytes drawn from a steam */
-int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, pdf_pkcs7_signer *signer, unsigned char *digest, int *digest_len);
-
-/* Report whether pkcs7 is supported in the current build */
-int pdf_pkcs7_supported(fz_context *ctx);
-
-#endif
diff --git a/platform/win32/libmupdf.vcproj b/platform/win32/libmupdf.vcproj
index 17217a68..0af5d4df 100644
--- a/platform/win32/libmupdf.vcproj
+++ b/platform/win32/libmupdf.vcproj
@@ -2137,10 +2137,6 @@
>
</File>
<File
- RelativePath="..\..\source\pdf\pdf-pkcs7.c"
- >
- </File>
- <File
RelativePath="..\..\source\pdf\pdf-portfolio.c"
>
</File>
@@ -2288,10 +2284,6 @@
>
</File>
<File
- RelativePath="..\..\include\mupdf\pdf\pdf-pkcs7.h"
- >
- </File>
- <File
RelativePath="..\..\include\mupdf\pdf\resource.h"
>
</File>
diff --git a/platform/win32/mupdf.vcproj b/platform/win32/mupdf.vcproj
index a85fe1ee..d9d3b765 100644
--- a/platform/win32/mupdf.vcproj
+++ b/platform/win32/mupdf.vcproj
@@ -1352,6 +1352,314 @@
<References>
</References>
<Files>
+ <Filter
+ Name="pkcs7"
+ >
+ <File
+ RelativePath="..\..\source\helpers\pkcs7\pkcs7-check.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Memento|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Memento|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugOpenssl|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugOpenssl|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseOpenssl|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseOpenssl|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugGProof|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugGProof|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="MementoCommercial|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="MementoCommercial|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugCommercial|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugCommercial|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseCommercial|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseCommercial|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\include\mupdf\helpers\pkcs7-check.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\helpers\pkcs7\pkcs7-openssl.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Memento|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Memento|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugOpenssl|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugOpenssl|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseOpenssl|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseOpenssl|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugGProof|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugGProof|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="MementoCommercial|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="MementoCommercial|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugCommercial|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugCommercial|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseCommercial|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseCommercial|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\include\mupdf\helpers\pkcs7-openssl.h"
+ >
+ </File>
+ </Filter>
<File
RelativePath="..\..\platform\x11\pdfapp.c"
>
diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c
index 6b04720d..ca869f16 100644
--- a/platform/x11/pdfapp.c
+++ b/platform/x11/pdfapp.c
@@ -1,5 +1,6 @@
#include "pdfapp.h"
#include "curl_stream.h"
+#include "mupdf/helpers/pkcs7-check.h"
#include <string.h>
#include <limits.h>
@@ -1713,6 +1714,7 @@ void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int sta
break;
case PDF_WIDGET_TYPE_SIGNATURE:
+#ifdef HAVE_LIBCRYPTO
if (state == -1)
{
char ebuf[256];
@@ -1730,6 +1732,9 @@ void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int sta
winwarn(app, ebuf);
}
}
+#else
+ winwarn(app, "No support for signatures in this build");
+#endif
break;
}
}
diff --git a/source/helpers/pkcs7/pkcs7-check.c b/source/helpers/pkcs7/pkcs7-check.c
new file mode 100644
index 00000000..72b6af90
--- /dev/null
+++ b/source/helpers/pkcs7/pkcs7-check.c
@@ -0,0 +1,128 @@
+#include "mupdf/fitz.h"
+#include "mupdf/pdf.h"
+#include "mupdf/helpers/pkcs7-openssl.h"
+#include "mupdf/helpers/pkcs7-check.h"
+
+#include <string.h>
+
+
+static void pdf_print_designated_name(pdf_pkcs7_designated_name *name, char *buf, int buflen)
+{
+ int i, n;
+ const char *part[] = {
+ "/CN=", name->cn,
+ "/O=", name->o,
+ "/OU=", name->ou,
+ "/emailAddress=", name->email,
+ "/C=", name->c};
+
+ if (buflen)
+ buf[0] = 0;
+
+ n = sizeof(part)/sizeof(*part);
+ for (i = 0; i < n; i++)
+ if (part[i])
+ fz_strlcat(buf, part[i], buflen);
+}
+
+int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, char *ebuf, int ebufsize)
+{
+ fz_stream *bytes = NULL;
+ char *contents = NULL;
+ int contents_len;
+ int res = 0;
+
+ if (pdf_xref_obj_is_unsaved_signature(doc, ((pdf_annot *)widget)->obj))
+ {
+ fz_strlcpy(ebuf, "Signed but document yet to be saved", ebufsize);
+ if (ebufsize > 0)
+ ebuf[ebufsize-1] = 0;
+ return 0;
+ }
+
+ fz_var(bytes);
+ fz_var(res);
+ fz_try(ctx)
+ {
+ contents_len = pdf_signature_widget_contents(ctx, doc, widget, &contents);
+ if (contents)
+ {
+ SignatureError err;
+
+ bytes = pdf_signature_widget_hash_bytes(ctx, doc, widget);
+ err = pkcs7_openssl_check_digest(ctx, bytes, contents, contents_len);
+ if (err == SignatureError_Okay)
+ err = pkcs7_openssl_check_certificate(contents, contents_len);
+ switch (err)
+ {
+ case SignatureError_Okay:
+ ebuf[0] = 0;
+ res = 1;
+ break;
+ case SignatureError_NoSignatures:
+ fz_strlcpy(ebuf, "No signatures", ebufsize);
+ break;
+ case SignatureError_NoCertificate:
+ fz_strlcpy(ebuf, "No certificate", ebufsize);
+ break;
+ case SignatureError_DocumentChanged:
+ fz_strlcpy(ebuf, "Document changed since signing", ebufsize);
+ break;
+ case SignatureError_SelfSigned:
+ fz_strlcpy(ebuf, "Self-signed certificate", ebufsize);
+ break;
+ case SignatureError_SelfSignedInChain:
+ fz_strlcpy(ebuf, "Self-signed certificate in chain", ebufsize);
+ break;
+ case SignatureError_NotTrusted:
+ fz_strlcpy(ebuf, "Certificate not trusted", ebufsize);
+ break;
+ default:
+ case SignatureError_Unknown:
+ fz_strlcpy(ebuf, "Unknown error", ebufsize);
+ break;
+ }
+
+ switch (err)
+ {
+ case SignatureError_SelfSigned:
+ case SignatureError_SelfSignedInChain:
+ case SignatureError_NotTrusted:
+ {
+ pdf_pkcs7_designated_name *name = pkcs7_openssl_designated_name(ctx, contents, contents_len);
+ if (name)
+ {
+ int len;
+
+ fz_strlcat(ebuf, ": ", ebufsize);
+ len = strlen(ebuf);
+ pdf_print_designated_name(name, ebuf + len, ebufsize - len);
+ pkcs7_opensll_drop_designated_name(ctx, name);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ res = 0;
+ fz_strlcpy(ebuf, "Not signed", ebufsize);
+ }
+ }
+ fz_always(ctx)
+ {
+ fz_drop_stream(ctx, bytes);
+ }
+ fz_catch(ctx)
+ {
+ res = 0;
+ fz_strlcpy(ebuf, fz_caught_message(ctx), ebufsize);
+ }
+
+ if (ebufsize > 0)
+ ebuf[ebufsize-1] = 0;
+
+ return res;
+}
diff --git a/source/pdf/pdf-pkcs7.c b/source/helpers/pkcs7/pkcs7-openssl.c
index 7f4e15b1..c0ca9093 100644
--- a/source/pdf/pdf-pkcs7.c
+++ b/source/helpers/pkcs7/pkcs7-openssl.c
@@ -1,11 +1,10 @@
#include "mupdf/fitz.h"
#include "mupdf/pdf.h"
-#include "../fitz/fitz-imp.h"
+#include "../../fitz/fitz-imp.h"
+#include "mupdf/helpers/pkcs7-openssl.h"
#include <string.h>
-#ifdef HAVE_LIBCRYPTO
-
/* Generated from resources/certs/AdobeCA.p7c */
static const char AdobeCA_p7c[] = {
48,130,4,208,6,9,42,134,72,134,247,13,1,7,2,160,130,4,193,48,130,4,189,2,
@@ -285,12 +284,14 @@ exit:
static SignatureError pk7_verify_cert(X509_STORE *cert_store, PKCS7 *p7)
{
- int res = SignatureError_Unknown;
+ int res = SignatureError_Okay;
int i;
STACK_OF(PKCS7_SIGNER_INFO) *sk;
X509_STORE_CTX *ctx;
ctx = X509_STORE_CTX_new();
+ if (!ctx)
+ return SignatureError_Unknown;
ERR_clear_error();
@@ -333,31 +334,35 @@ static SignatureError pk7_verify_cert(X509_STORE *cert_store, PKCS7 *p7)
if (!X509_STORE_CTX_init(ctx, cert_store, cert, certs))
{
- res = 0;
- PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB);
+ res = SignatureError_Unknown;
goto exit;
}
- X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
+ if (!X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN))
+ {
+ res = SignatureError_Unknown;
+ goto exit;
+ }
+ /* X509_verify_cert may return an error, but in all such cases
+ * it sets a context error */
X509_verify_cert(ctx);
X509_STORE_CTX_cleanup(ctx);
ctx_err = X509_STORE_CTX_get_error(ctx);
switch (ctx_err)
{
case X509_V_OK:
- res = SignatureError_Okay;
break;
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
res = SignatureError_SelfSigned;
- break;
+ goto exit;
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
res = SignatureError_SelfSignedInChain;
- break;
+ goto exit;
default:
- break;
+ res = SignatureError_Unknown;
+ goto exit;
}
- goto exit;
}
exit:
@@ -367,12 +372,11 @@ exit:
return res;
}
-SignatureError pdf_pkcs7_check_digest(fz_context *ctx, fz_stream *stm, char *sig, int sig_len)
+SignatureError pkcs7_openssl_check_digest(fz_context *ctx, fz_stream *stm, char *sig, int sig_len)
{
PKCS7 *pk7sig = NULL;
BIO *bsig = NULL;
BIO *bdata = NULL;
- STACK_OF(X509) *certs = NULL;
int res = SignatureError_Unknown;
bsig = BIO_new_mem_buf(sig, sig_len);
@@ -394,7 +398,7 @@ exit:
return res;
}
-SignatureError pdf_pkcs7_check_certificate(char *sig, int sig_len)
+SignatureError pkcs7_openssl_check_certificate(char *sig, int sig_len)
{
PKCS7 *pk7sig = NULL;
PKCS7 *pk7cert = NULL;
@@ -451,16 +455,24 @@ typedef struct pdf_pkcs7_designated_name_openssl_s
char buf[8192];
} pdf_pkcs7_designated_name_openssl;
-struct pdf_pkcs7_signer_s
+void pkcs7_opensll_drop_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *dn)
{
+ fz_free(ctx, dn);
+}
+
+typedef struct
+{
+ pdf_pkcs7_signer base;
+ fz_context *ctx;
int refs;
X509 *x509;
EVP_PKEY *pkey;
-};
+} openssl_signer;
-void pdf_pkcs7_drop_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *dn)
+static void signer_drop_designated_name(pdf_pkcs7_signer *signer, pdf_pkcs7_designated_name *dn)
{
- fz_free(ctx, dn);
+ openssl_signer *osigner = (openssl_signer *)signer;
+ fz_free(osigner->ctx, dn);
}
static void add_from_bags(X509 **pX509, EVP_PKEY **pPkey, const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pw);
@@ -524,104 +536,20 @@ static void add_from_bags(X509 **pX509, EVP_PKEY **pPkey, const STACK_OF(PKCS12_
add_from_bag(pX509, pPkey, sk_PKCS12_SAFEBAG_value(bags, i), pw);
}
-pdf_pkcs7_signer *pdf_pkcs7_read_pfx(fz_context *ctx, const char *pfile, const char *pw)
+static pdf_pkcs7_signer *keep_signer(pdf_pkcs7_signer *signer)
{
- BIO *pfxbio = NULL;
- PKCS12 *p12 = NULL;
- STACK_OF(PKCS7) *asafes;
- pdf_pkcs7_signer *signer = NULL;
- int i;
-
- fz_var(pfxbio);
- fz_var(p12);
- fz_var(signer);
- fz_try(ctx)
- {
- signer = fz_malloc_struct(ctx, pdf_pkcs7_signer);
- signer->refs = 1;
-
- OpenSSL_add_all_algorithms();
-
- EVP_add_digest(EVP_md5());
- EVP_add_digest(EVP_sha1());
-
- ERR_load_crypto_strings();
-
- ERR_clear_error();
-
- pfxbio = BIO_new_file(pfile, "rb");
- if (pfxbio == NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "Can't open pfx file: %s", pfile);
-
- p12 = d2i_PKCS12_bio(pfxbio, NULL);
- if (p12 == NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "Invalid pfx file: %s", pfile);
-
- asafes = PKCS12_unpack_authsafes(p12);
- if (asafes == NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "Invalid pfx file: %s", pfile);
-
- /* Nothing in this for loop can fz_throw */
- for (i = 0; i < sk_PKCS7_num(asafes); i++)
- {
- PKCS7 *p7;
- STACK_OF(PKCS12_SAFEBAG) *bags;
- int bagnid;
-
- p7 = sk_PKCS7_value(asafes, i);
- bagnid = OBJ_obj2nid(p7->type);
- switch (bagnid)
- {
- case NID_pkcs7_data:
- bags = PKCS12_unpack_p7data(p7);
- break;
- case NID_pkcs7_encrypted:
- bags = PKCS12_unpack_p7encdata(p7, pw, (int)strlen(pw));
- break;
- default:
- continue;
- }
-
- if (bags)
- {
- add_from_bags(&signer->x509, &signer->pkey, bags, pw);
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- }
- }
- sk_PKCS7_pop_free (asafes, PKCS7_free);
-
- if (signer->pkey == NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to obtain public key");
-
- if (signer->x509 == NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to obtain certificate");
- }
- fz_always(ctx)
- {
- BIO_free(pfxbio);
- PKCS12_free(p12);
- }
- fz_catch(ctx)
- {
- pdf_pkcs7_drop_signer(ctx, signer);
- fz_rethrow(ctx);
- }
-
- return signer;
+ openssl_signer *osigner = (openssl_signer *)signer;
+ return fz_keep_imp(osigner->ctx, osigner, &osigner->refs);
}
-pdf_pkcs7_signer *pdf_pkcs7_keep_signer(fz_context *ctx, pdf_pkcs7_signer *signer)
+static void drop_signer(pdf_pkcs7_signer *signer)
{
- return fz_keep_imp(ctx, signer, &signer->refs);
-}
-
-void pdf_pkcs7_drop_signer(fz_context *ctx, pdf_pkcs7_signer *signer)
-{
- if (fz_drop_imp(ctx, signer, &signer->refs))
+ openssl_signer *osigner = (openssl_signer *)signer;
+ if (fz_drop_imp(osigner->ctx, osigner, &osigner->refs))
{
- X509_free(signer->x509);
- EVP_PKEY_free(signer->pkey);
- fz_free(ctx, signer);
+ X509_free(osigner->x509);
+ EVP_PKEY_free(osigner->pkey);
+ fz_free(osigner->ctx, osigner);
}
}
@@ -649,13 +577,16 @@ static pdf_pkcs7_designated_name *x509_designated_name(fz_context *ctx, X509 *x5
return (pdf_pkcs7_designated_name *)dn;
}
-pdf_pkcs7_designated_name *pdf_pkcs7_signer_designated_name(fz_context *ctx, pdf_pkcs7_signer *signer)
+static pdf_pkcs7_designated_name *signer_designated_name(pdf_pkcs7_signer *signer)
{
- return x509_designated_name(ctx, signer->x509);
+ openssl_signer *osigner = (openssl_signer *)signer;
+ return x509_designated_name(osigner->ctx, osigner->x509);
}
-int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, pdf_pkcs7_signer *signer, unsigned char *digest, int *digest_len)
+static int signer_create_digest(pdf_pkcs7_signer *signer, fz_stream *in, unsigned char *digest, int *digest_len)
{
+ openssl_signer *osigner = (openssl_signer *)signer;
+ fz_context *ctx = osigner->ctx;
int res = 0;
BIO *bdata = NULL;
BIO *bp7in = NULL;
@@ -676,12 +607,12 @@ int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, pdf_pkcs7_signer *si
goto exit;
PKCS7_set_type(p7, NID_pkcs7_signed);
- si = PKCS7_add_signature(p7, signer->x509, signer->pkey, EVP_sha1());
+ si = PKCS7_add_signature(p7, osigner->x509, osigner->pkey, EVP_sha1());
if (si == NULL)
goto exit;
PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
- PKCS7_add_certificate(p7, signer->x509);
+ PKCS7_add_certificate(p7, osigner->x509);
PKCS7_content_new(p7, NID_pkcs7_data);
PKCS7_set_detached(p7, 1);
@@ -725,7 +656,100 @@ exit:
return res;
}
-pdf_pkcs7_designated_name *pdf_cert_designated_name(fz_context *ctx, char *sig, int sig_len)
+pdf_pkcs7_signer *pkcs7_openssl_read_pfx(fz_context *ctx, const char *pfile, const char *pw)
+{
+ BIO *pfxbio = NULL;
+ PKCS12 *p12 = NULL;
+ STACK_OF(PKCS7) *asafes;
+ openssl_signer *signer = NULL;
+ int i;
+
+ fz_var(pfxbio);
+ fz_var(p12);
+ fz_var(signer);
+ fz_try(ctx)
+ {
+ signer = fz_malloc_struct(ctx, openssl_signer);
+ signer->refs = 1;
+
+ OpenSSL_add_all_algorithms();
+
+ EVP_add_digest(EVP_md5());
+ EVP_add_digest(EVP_sha1());
+
+ ERR_load_crypto_strings();
+
+ ERR_clear_error();
+
+ pfxbio = BIO_new_file(pfile, "rb");
+ if (pfxbio == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Can't open pfx file: %s", pfile);
+
+ p12 = d2i_PKCS12_bio(pfxbio, NULL);
+ if (p12 == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Invalid pfx file: %s", pfile);
+
+ asafes = PKCS12_unpack_authsafes(p12);
+ if (asafes == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Invalid pfx file: %s", pfile);
+
+ /* Nothing in this for loop can fz_throw */
+ for (i = 0; i < sk_PKCS7_num(asafes); i++)
+ {
+ PKCS7 *p7;
+ STACK_OF(PKCS12_SAFEBAG) *bags;
+ int bagnid;
+
+ p7 = sk_PKCS7_value(asafes, i);
+ bagnid = OBJ_obj2nid(p7->type);
+ switch (bagnid)
+ {
+ case NID_pkcs7_data:
+ bags = PKCS12_unpack_p7data(p7);
+ break;
+ case NID_pkcs7_encrypted:
+ bags = PKCS12_unpack_p7encdata(p7, pw, (int)strlen(pw));
+ break;
+ default:
+ continue;
+ }
+
+ if (bags)
+ {
+ add_from_bags(&signer->x509, &signer->pkey, bags, pw);
+ sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+ }
+ }
+ sk_PKCS7_pop_free (asafes, PKCS7_free);
+
+ if (signer->pkey == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to obtain public key");
+
+ if (signer->x509 == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to obtain certificate");
+
+ signer->ctx = ctx;
+ signer->base.keep = keep_signer;
+ signer->base.drop = drop_signer;
+ signer->base.designated_name = signer_designated_name;
+ signer->base.drop_designated_name = signer_drop_designated_name;
+ signer->base.create_digest = signer_create_digest;
+ }
+ fz_always(ctx)
+ {
+ BIO_free(pfxbio);
+ PKCS12_free(p12);
+ }
+ fz_catch(ctx)
+ {
+ drop_signer(&signer->base);
+ fz_rethrow(ctx);
+ }
+
+ return &signer->base;
+}
+
+pdf_pkcs7_designated_name *pkcs7_openssl_designated_name(fz_context *ctx, char *sig, int sig_len)
{
pdf_pkcs7_designated_name *name = NULL;
PKCS7 *pk7sig = NULL;
@@ -752,61 +776,3 @@ exit:
return name;
}
-
-
-int pdf_pkcs7_supported(fz_context *ctx)
-{
- return 1;
-}
-
-#else /* HAVE_LIBCRYPTO */
-
-SignatureError pdf_pkcs7_check_digest(fz_context *ctx, fz_stream *stm, char *sig, int sig_len)
-{
- return SignatureError_Unknown;
-}
-
-SignatureError pdf_pkcs7_check_certificate(char *sig, int sig_len)
-{
- return SignatureError_Unknown;
-}
-
-pdf_pkcs7_designated_name *pdf_cert_designated_name(fz_context *ctx, char *sig, int sig_len)
-{
- return NULL;
-}
-
-void pdf_pkcs7_drop_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *dn)
-{
-}
-
-pdf_pkcs7_signer *pdf_pkcs7_read_pfx(fz_context *ctx, const char *pfile, const char *pw)
-{
- return NULL;
-}
-
-pdf_pkcs7_signer *pdf_pkcs7_keep_signer(fz_context *ctx, pdf_pkcs7_signer *signer)
-{
- return NULL;
-}
-
-void pdf_pkcs7_drop_signer(fz_context *ctx, pdf_pkcs7_signer *signer)
-{
-}
-
-pdf_pkcs7_designated_name *pdf_pkcs7_signer_designated_name(fz_context *ctx, pdf_pkcs7_signer *signer)
-{
- return NULL;
-}
-
-int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, pdf_pkcs7_signer *signer, unsigned char *digest, int *digest_len)
-{
- return 0;
-}
-
-int pdf_pkcs7_supported(fz_context *ctx)
-{
- return 0;
-}
-
-#endif /* HAVE_LIBCRYPTO */
diff --git a/source/pdf/pdf-signature.c b/source/pdf/pdf-signature.c
index 3d96a261..3c882f54 100644
--- a/source/pdf/pdf-signature.c
+++ b/source/pdf/pdf-signature.c
@@ -5,25 +5,6 @@
#include <string.h>
-static void pdf_print_designated_name(pdf_pkcs7_designated_name *name, char *buf, int buflen)
-{
- int i, n;
- const char *part[] = {
- "/CN=", name->cn,
- "/O=", name->o,
- "/OU=", name->ou,
- "/emailAddress=", name->email,
- "/C=", name->c};
-
- if (buflen)
- buf[0] = 0;
-
- n = sizeof(part)/sizeof(*part);
- for (i = 0; i < n; i++)
- if (part[i])
- fz_strlcat(buf, part[i], buflen);
-}
-
void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, int hexdigest_offset, int hexdigest_length, pdf_pkcs7_signer *signer)
{
fz_stream *in = NULL;
@@ -53,7 +34,7 @@ void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, int
digest_len = (hexdigest_length - 2) / 2;
digest = fz_malloc(ctx, digest_len);
- res = pdf_pkcs7_create_digest(ctx, in, signer, digest, &digest_len);
+ res = signer->create_digest(signer, in, digest, &digest_len);
if (!res)
fz_throw(ctx, FZ_ERROR_GENERIC, "pdf_pkcs7_create_digest failed");
@@ -77,111 +58,8 @@ void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, int
}
}
-int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, char *ebuf, int ebufsize)
-{
- fz_stream *bytes = NULL;
- char *contents = NULL;
- int contents_len;
- int res = 0;
-
- if (pdf_xref_obj_is_unsaved_signature(doc, ((pdf_annot *)widget)->obj))
- {
- fz_strlcpy(ebuf, "Signed but document yet to be saved", ebufsize);
- if (ebufsize > 0)
- ebuf[ebufsize-1] = 0;
- return 0;
- }
-
- fz_var(bytes);
- fz_var(res);
- fz_try(ctx)
- {
- contents_len = pdf_signature_widget_contents(ctx, doc, widget, &contents);
- if (contents)
- {
- SignatureError err;
-
- bytes = pdf_signature_widget_hash_bytes(ctx, doc, widget);
- err = pdf_pkcs7_check_digest(ctx, bytes, contents, contents_len);
- if (err == SignatureError_Okay)
- err = pdf_pkcs7_check_certificate(contents, contents_len);
- switch (err)
- {
- case SignatureError_Okay:
- ebuf[0] = 0;
- res = 1;
- break;
- case SignatureError_NoSignatures:
- fz_strlcpy(ebuf, "No signatures", ebufsize);
- break;
- case SignatureError_NoCertificate:
- fz_strlcpy(ebuf, "No certificate", ebufsize);
- break;
- case SignatureError_DocumentChanged:
- fz_strlcpy(ebuf, "Document changed since signing", ebufsize);
- break;
- case SignatureError_SelfSigned:
- fz_strlcpy(ebuf, "Self-signed certificate", ebufsize);
- break;
- case SignatureError_SelfSignedInChain:
- fz_strlcpy(ebuf, "Self-signed certificate in chain", ebufsize);
- break;
- case SignatureError_NotTrusted:
- fz_strlcpy(ebuf, "Certificate not trusted", ebufsize);
- break;
- default:
- case SignatureError_Unknown:
- fz_strlcpy(ebuf, "Unknown error", ebufsize);
- break;
- }
-
- switch (err)
- {
- case SignatureError_SelfSigned:
- case SignatureError_SelfSignedInChain:
- case SignatureError_NotTrusted:
- {
- pdf_pkcs7_designated_name *name = pdf_cert_designated_name(ctx, contents, contents_len);
- if (name)
- {
- int len;
-
- fz_strlcat(ebuf, ": ", ebufsize);
- len = strlen(ebuf);
- pdf_print_designated_name(name, ebuf + len, ebufsize - len);
- pdf_pkcs7_drop_designated_name(ctx, name);
- }
- }
- break;
- default:
- break;
- }
- }
- else
- {
- res = 0;
- fz_strlcpy(ebuf, "Not signed", ebufsize);
- }
- }
- fz_always(ctx)
- {
- fz_drop_stream(ctx, bytes);
- }
- fz_catch(ctx)
- {
- res = 0;
- fz_strlcpy(ebuf, fz_caught_message(ctx), ebufsize);
- }
-
- if (ebufsize > 0)
- ebuf[ebufsize-1] = 0;
-
- return res;
-}
-
-void pdf_sign_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, const char *sigfile, const char *password)
+void pdf_sign_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, pdf_pkcs7_signer *signer)
{
- pdf_pkcs7_signer *signer = pdf_pkcs7_read_pfx(ctx, sigfile, password);
pdf_pkcs7_designated_name *dn = NULL;
fz_buffer *fzbuf = NULL;
@@ -197,7 +75,7 @@ void pdf_sign_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget,
/* Create an appearance stream only if the signature is intended to be visible */
if (!fz_is_empty_rect(&rect))
{
- dn = pdf_pkcs7_signer_designated_name(ctx, signer);
+ dn = signer->designated_name(signer);
fzbuf = fz_new_buffer(ctx, 256);
if (!dn->cn)
fz_throw(ctx, FZ_ERROR_GENERIC, "Certificate has no common name");
@@ -222,8 +100,7 @@ void pdf_sign_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget,
}
fz_always(ctx)
{
- pdf_pkcs7_drop_signer(ctx, signer);
- pdf_pkcs7_drop_designated_name(ctx, dn);
+ signer->drop_designated_name(signer, dn);
fz_drop_buffer(ctx, fzbuf);
}
fz_catch(ctx)
@@ -231,8 +108,3 @@ void pdf_sign_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget,
fz_rethrow(ctx);
}
}
-
-int pdf_signatures_supported(fz_context *ctx)
-{
- return pdf_pkcs7_supported(ctx);
-}
diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c
index 0ab76a35..7b163813 100644
--- a/source/pdf/pdf-write.c
+++ b/source/pdf/pdf-write.c
@@ -2708,7 +2708,7 @@ static void complete_signatures(fz_context *ctx, pdf_document *doc, pdf_write_st
{
xref->unsaved_sigs = usig->next;
pdf_drop_obj(ctx, usig->field);
- pdf_pkcs7_drop_signer(ctx, usig->signer);
+ usig->signer->drop(usig->signer);
fz_free(ctx, usig);
}
}
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
index 1dc3b7d8..7e38706b 100644
--- a/source/pdf/pdf-xref.c
+++ b/source/pdf/pdf-xref.c
@@ -59,7 +59,7 @@ static void pdf_drop_xref_sections_imp(fz_context *ctx, pdf_document *doc, pdf_x
{
xref->unsaved_sigs = usig->next;
pdf_drop_obj(ctx, usig->field);
- pdf_pkcs7_drop_signer(ctx, usig->signer);
+ usig->signer->drop(usig->signer);
fz_free(ctx, usig);
}
}
@@ -418,7 +418,7 @@ void pdf_xref_store_unsaved_signature(fz_context *ctx, pdf_document *doc, pdf_ob
* saving time */
unsaved_sig = fz_malloc_struct(ctx, pdf_unsaved_sig);
unsaved_sig->field = pdf_keep_obj(ctx, field);
- unsaved_sig->signer = pdf_pkcs7_keep_signer(ctx, signer);
+ unsaved_sig->signer = signer->keep(signer);
unsaved_sig->next = NULL;
if (xref->unsaved_sigs_end == NULL)
xref->unsaved_sigs_end = &xref->unsaved_sigs;
diff --git a/source/tools/pdfsign.c b/source/tools/pdfsign.c
index bc14be41..434c9332 100644
--- a/source/tools/pdfsign.c
+++ b/source/tools/pdfsign.c
@@ -4,6 +4,7 @@
#include "mupdf/fitz.h"
#include "mupdf/pdf.h"
+#include "mupdf/helpers/pkcs7-check.h"
#include <string.h>
#include <stdlib.h>
@@ -22,10 +23,14 @@ static void usage(void)
void verify_signature(fz_context *ctx, pdf_document *doc, int n, pdf_widget *widget)
{
+#ifdef HAVE_LIBCRYPTO
char msg[256];
printf("verifying signature on page %d\n", n+1);
pdf_check_signature(ctx, doc, widget, msg, sizeof msg);
printf(" result: '%s'\n", msg);
+#else
+ printf("No signature support in this build\n");
+#endif
}
void verify_page(fz_context *ctx, pdf_document *doc, int n, pdf_page *page)