summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2020-04-04 14:34:27 +0100
committerRobin Watts <Robin.Watts@artifex.com>2020-04-07 17:55:00 +0100
commit3f9ee8f4dfa03e9680cf0777f1518e305cb48c09 (patch)
tree1351308ab1c02b5188949b0816eb51a281d1db61
parent4c420da4ed846918a3de4e0912fd95cffeba7c7d (diff)
pkcs7: refactor signing interface.
Move the pkcs7 check functions to pkcs7-openssl.c/.h and remove pkcs7-check.c/h. Move pdf pkcs7 sign/verify interfaces from pdf/document.h to pdf/form.h. Fix up redundant references to pkcs7-check.h. Update the gl app and tools to use the slightly reworked pkcs7 interface.
-rw-r--r--Makefile4
-rw-r--r--include/mupdf/helpers/pkcs7-check.h18
-rw-r--r--include/mupdf/helpers/pkcs7-openssl.h5
-rw-r--r--include/mupdf/pdf/crypt.h1
-rw-r--r--include/mupdf/pdf/document.h54
-rw-r--r--include/mupdf/pdf/form.h84
-rw-r--r--platform/gl/gl-form.c25
-rw-r--r--platform/gl/gl-main.c21
-rw-r--r--platform/win32/libpkcs7.vcxproj4
-rw-r--r--platform/win32/libpkcs7.vcxproj.filters6
-rw-r--r--platform/x11/pdfapp.c1
-rw-r--r--source/helpers/pkcs7/pkcs7-check.c212
-rw-r--r--source/helpers/pkcs7/pkcs7-openssl.c169
-rw-r--r--source/pdf/pdf-form.c2
-rw-r--r--source/pdf/pdf-signature.c213
-rw-r--r--source/pdf/pdf-write.c4
-rw-r--r--source/pdf/pdf-xref.c4
-rw-r--r--source/tools/murun.c5
-rw-r--r--source/tools/pdfsign.c57
19 files changed, 466 insertions, 423 deletions
diff --git a/Makefile b/Makefile
index a8ddbcd9b..a81732b3d 100644
--- a/Makefile
+++ b/Makefile
@@ -218,8 +218,8 @@ TOOL_APPS += $(MUTOOL_EXE)
MURASTER_OBJ := $(OUT)/source/tools/muraster.o
MURASTER_EXE := $(OUT)/muraster
-$(MURASTER_EXE) : $(MURASTER_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(THREAD_LIB)
- $(LINK_CMD) $(THIRD_LIBS) $(THREADING_LIBS)
+$(MURASTER_EXE) : $(MURASTER_OBJ) $(MUPDF_LIB) $(THIRD_LIB) $(PKCS7_LIB) $(THREAD_LIB)
+ $(LINK_CMD) $(THIRD_LIBS) $(THREADING_LIBS) $(LIBCRYPTO_LIBS)
TOOL_APPS += $(MURASTER_EXE)
ifeq ($(HAVE_GLUT),yes)
diff --git a/include/mupdf/helpers/pkcs7-check.h b/include/mupdf/helpers/pkcs7-check.h
deleted file mode 100644
index 71d517de6..000000000
--- a/include/mupdf/helpers/pkcs7-check.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef MUPDF_PKCS7_CHECK_H
-#define MUPDF_PKCS7_CHECK_H
-
-char *pdf_signature_error_description(pdf_signature_error err);
-void pdf_signature_designated_name(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char *buf, size_t buflen);
-pdf_signature_error pdf_check_digest(fz_context *ctx, pdf_document *doc, pdf_obj *signature);
-pdf_signature_error pdf_check_certificate(fz_context *ctx, pdf_document *doc, pdf_obj *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_obj *signature, char *ebuf, size_t ebufsize);
-
-int pdf_supports_signatures(fz_context *ctx);
-
-#endif
diff --git a/include/mupdf/helpers/pkcs7-openssl.h b/include/mupdf/helpers/pkcs7-openssl.h
index 4218b6447..85d151821 100644
--- a/include/mupdf/helpers/pkcs7-openssl.h
+++ b/include/mupdf/helpers/pkcs7-openssl.h
@@ -15,10 +15,9 @@ pdf_signature_error pkcs7_openssl_check_certificate(char *sig, size_t sig_len);
/* Obtain the designated name information from signature's certificate */
pdf_pkcs7_designated_name *pkcs7_openssl_designated_name(fz_context *ctx, char *sig, size_t sig_len);
-/* Free the resources associated with designated name information */
-void pkcs7_openssl_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);
+pdf_pkcs7_verifier *pkcs7_openssl_new_verifier(fz_context *ctx);
+
#endif
diff --git a/include/mupdf/pdf/crypt.h b/include/mupdf/pdf/crypt.h
index e308af6b6..9f33c5ba2 100644
--- a/include/mupdf/pdf/crypt.h
+++ b/include/mupdf/pdf/crypt.h
@@ -63,6 +63,7 @@ int pdf_signature_incremental_change_since_signing(fz_context *ctx, pdf_document
size_t pdf_signature_contents(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char **contents);
+typedef struct pdf_pkcs7_designated_name_s pdf_pkcs7_designated_name;
void pdf_sign_signature(fz_context *ctx, pdf_widget *widget, pdf_pkcs7_signer *signer);
void pdf_clear_signature(fz_context *ctx, pdf_widget *widget);
diff --git a/include/mupdf/pdf/document.h b/include/mupdf/pdf/document.h
index e609d8ef0..595d42ca1 100644
--- a/include/mupdf/pdf/document.h
+++ b/include/mupdf/pdf/document.h
@@ -113,60 +113,8 @@ void pdf_set_layer_config_as_default(fz_context *ctx, pdf_document *doc);
int pdf_has_unsaved_changes(fz_context *ctx, pdf_document *doc);
-typedef enum
-{
- PDF_SIGNATURE_ERROR_OKAY,
- PDF_SIGNATURE_ERROR_NO_SIGNATURES,
- PDF_SIGNATURE_ERROR_NO_CERTIFICATE,
- PDF_SIGNATURE_ERROR_DIGEST_FAILURE,
- PDF_SIGNATURE_ERROR_SELF_SIGNED,
- PDF_SIGNATURE_ERROR_SELF_SIGNED_IN_CHAIN,
- PDF_SIGNATURE_ERROR_NOT_TRUSTED,
- PDF_SIGNATURE_ERROR_UNKNOWN
-} pdf_signature_error;
-
-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);
-
-/* Predict the size of the digest. The actual digest returned by create_digest will be no greater in size */
-typedef size_t (pdf_pkcs7_max_digest_size_fn)(pdf_pkcs7_signer *signer);
-
-/* Create a signature based on ranges of bytes drawn from a stream */
-typedef int (pdf_pkcs7_create_digest_fn)(pdf_pkcs7_signer *signer, fz_stream *in, unsigned char *digest, size_t *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_max_digest_size_fn *max_digest_size;
- pdf_pkcs7_create_digest_fn *create_digest;
-};
-
/* Unsaved signature fields */
+typedef struct pdf_pkcs7_signer_s pdf_pkcs7_signer;
typedef struct pdf_unsaved_sig_s pdf_unsaved_sig;
struct pdf_unsaved_sig_s
diff --git a/include/mupdf/pdf/form.h b/include/mupdf/pdf/form.h
index 8cd7531cf..a641f9fb2 100644
--- a/include/mupdf/pdf/form.h
+++ b/include/mupdf/pdf/form.h
@@ -101,11 +101,95 @@ int pdf_set_field_value(fz_context *ctx, pdf_document *doc, pdf_obj *field, cons
int pdf_set_text_field_value(fz_context *ctx, pdf_widget *widget, const char *value);
int pdf_set_choice_field_value(fz_context *ctx, pdf_widget *widget, const char *value);
+typedef struct pdf_pkcs7_designated_name_s
+{
+ char *cn;
+ char *o;
+ char *ou;
+ char *email;
+ char *c;
+}
+pdf_pkcs7_designated_name;
+
+typedef enum
+{
+ PDF_SIGNATURE_ERROR_OKAY,
+ PDF_SIGNATURE_ERROR_NO_SIGNATURES,
+ PDF_SIGNATURE_ERROR_NO_CERTIFICATE,
+ PDF_SIGNATURE_ERROR_DIGEST_FAILURE,
+ PDF_SIGNATURE_ERROR_SELF_SIGNED,
+ PDF_SIGNATURE_ERROR_SELF_SIGNED_IN_CHAIN,
+ PDF_SIGNATURE_ERROR_NOT_TRUSTED,
+ PDF_SIGNATURE_ERROR_UNKNOWN
+} pdf_signature_error;
+
+/* 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_signer_fn)(fz_context *ctx, pdf_pkcs7_signer *signer);
+
+/* Drop a reference for a signer object */
+typedef void (pdf_pkcs7_drop_signer_fn)(fz_context *ctx, pdf_pkcs7_signer *signer);
+
+/* Obtain the designated name information from a signer object */
+typedef pdf_pkcs7_designated_name *(pdf_pkcs7_get_signing_name_fn)(fz_context *ctx, pdf_pkcs7_signer *signer);
+
+/* Predict the size of the digest. The actual digest returned by create_digest will be no greater in size */
+typedef size_t (pdf_pkcs7_max_digest_size_fn)(fz_context *ctx, pdf_pkcs7_signer *signer);
+
+/* Create a signature based on ranges of bytes drawn from a stream */
+typedef int (pdf_pkcs7_create_digest_fn)(fz_context *ctx, pdf_pkcs7_signer *signer, fz_stream *in, unsigned char *digest, size_t digest_len);
+
+struct pdf_pkcs7_signer_s
+{
+ pdf_pkcs7_keep_signer_fn *keep;
+ pdf_pkcs7_drop_signer_fn *drop;
+ pdf_pkcs7_get_signing_name_fn *get_signing_name;
+ pdf_pkcs7_max_digest_size_fn *max_digest_size;
+ pdf_pkcs7_create_digest_fn *create_digest;
+};
+
+typedef struct pdf_pkcs7_verifier_s pdf_pkcs7_verifier;
+
+typedef void (pdf_pkcs7_drop_verifier_fn)(fz_context *ctx, pdf_pkcs7_verifier *verifier);
+typedef pdf_signature_error (pdf_pkcs7_check_certificate_fn)(fz_context *ctx, pdf_pkcs7_verifier *verifier, unsigned char *signature, size_t len);
+typedef pdf_signature_error (pdf_pkcs7_check_digest_fn)(fz_context *ctx, pdf_pkcs7_verifier *verifier, fz_stream *in, unsigned char *signature, size_t len);
+typedef pdf_pkcs7_designated_name *(pdf_pkcs7_get_signatory_fn)(fz_context *ctx, pdf_pkcs7_verifier *verifier, unsigned char *signature, size_t len);
+
+struct pdf_pkcs7_verifier_s
+{
+ pdf_pkcs7_drop_verifier_fn *drop;
+ pdf_pkcs7_check_certificate_fn *check_certificate;
+ pdf_pkcs7_check_digest_fn *check_digest;
+ pdf_pkcs7_get_signatory_fn *get_signatory;
+};
+
int pdf_signature_is_signed(fz_context *ctx, pdf_document *doc, pdf_obj *field);
void pdf_signature_set_value(fz_context *ctx, pdf_document *doc, pdf_obj *field, pdf_pkcs7_signer *signer, int64_t stime);
int pdf_count_signatures(fz_context *ctx, pdf_document *doc);
+char *pdf_signature_error_description(pdf_signature_error err);
+
+pdf_pkcs7_designated_name *pdf_signature_get_signatory(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature);
+void pdf_signature_drop_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *name);
+char *pdf_signature_format_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *name);
+
+pdf_signature_error pdf_check_digest(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature);
+pdf_signature_error pdf_check_certificate(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *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_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature, char *ebuf, size_t ebufsize);
+
+void pdf_drop_signer(fz_context *ctx, pdf_pkcs7_signer *signer);
+void pdf_drop_verifier(fz_context *ctx, pdf_pkcs7_verifier *verifier);
+
void pdf_field_reset(fz_context *ctx, pdf_document *doc, pdf_obj *field);
pdf_obj *pdf_lookup_field(fz_context *ctx, pdf_obj *form, const char *name);
diff --git a/platform/gl/gl-form.c b/platform/gl/gl-form.c
index a10d7faa5..a2d5b13af 100644
--- a/platform/gl/gl-form.c
+++ b/platform/gl/gl-form.c
@@ -7,11 +7,10 @@
#define PATH_MAX 2048
#endif
-#include "mupdf/helpers/pkcs7-check.h"
#include "mupdf/helpers/pkcs7-openssl.h"
static pdf_widget *sig_widget;
-static char sig_designated_name[500];
+static char *sig_designated_name = NULL;
static pdf_signature_error sig_cert_error;
static pdf_signature_error sig_digest_error;
static int sig_valid_until;
@@ -35,8 +34,7 @@ int do_sign(void)
}
fz_always(ctx)
{
- if (signer)
- signer->drop(signer);
+ pdf_drop_signer(ctx, signer);
}
fz_catch(ctx)
{
@@ -206,10 +204,23 @@ static void show_sig_dialog(pdf_widget *widget)
if (pdf_signature_is_signed(ctx, pdf, widget->obj))
{
- sig_cert_error = pdf_check_certificate(ctx, pdf, widget->obj);
- sig_digest_error = pdf_check_digest(ctx, pdf, widget->obj);
+ pdf_pkcs7_verifier *verifier;
+ pdf_pkcs7_designated_name *dn;
+
sig_valid_until = pdf_validate_signature(ctx, widget);
- pdf_signature_designated_name(ctx, pdf, widget->obj, sig_designated_name, sizeof(sig_designated_name));
+
+ verifier = pkcs7_openssl_new_verifier(ctx);
+
+ sig_cert_error = pdf_check_certificate(ctx, verifier, pdf, widget->obj);
+ sig_digest_error = pdf_check_digest(ctx, verifier, pdf, widget->obj);
+
+ dn = pdf_signature_get_signatory(ctx, verifier, pdf, widget->obj);
+ fz_free(ctx, sig_designated_name);
+ sig_designated_name = pdf_signature_format_designated_name(ctx, dn);
+ pdf_signature_drop_designated_name(ctx, dn);
+
+ pdf_drop_verifier(ctx, verifier);
+
ui.dialog = sig_verify_dialog;
}
else
diff --git a/platform/gl/gl-main.c b/platform/gl/gl-main.c
index 512bcef0a..65804f5e7 100644
--- a/platform/gl/gl-main.c
+++ b/platform/gl/gl-main.c
@@ -12,7 +12,6 @@
#include <signal.h>
#endif
-#include "mupdf/helpers/pkcs7-check.h"
#include "mupdf/helpers/pkcs7-openssl.h"
#include "mujs.h"
@@ -1780,17 +1779,15 @@ static void do_info(void)
{
if (pdf_signature_is_signed(ctx, pdf, field))
{
- if (pdf_supports_signatures(ctx))
- {
- pdf_signature_error sig_cert_error = pdf_check_certificate(ctx, pdf, field);
- pdf_signature_error sig_digest_error = pdf_check_digest(ctx, pdf, field);
- ui_label("Signature %d: CERT: %s, DIGEST: %s%s", i+1,
- short_signature_error_desc(sig_cert_error),
- short_signature_error_desc(sig_digest_error),
- pdf_signature_incremental_change_since_signing(ctx, pdf, field) ? ", Changed since": "");
- }
- else
- ui_label("Signature %d: Signed (cannot test validity)", i+1);
+ pdf_pkcs7_verifier *verifier = pkcs7_openssl_new_verifier(ctx);
+ pdf_signature_error sig_cert_error = pdf_check_certificate(ctx, verifier, pdf, field);
+ pdf_signature_error sig_digest_error = pdf_check_digest(ctx, verifier, pdf, field);
+ ui_label("Signature %d: CERT: %s, DIGEST: %s%s", i+1,
+ short_signature_error_desc(sig_cert_error),
+ short_signature_error_desc(sig_digest_error),
+ pdf_signature_incremental_change_since_signing(ctx, pdf, field) ? ", Changed since": "");
+
+ pdf_drop_verifier(ctx, verifier);
}
else
ui_label("Signature %d: Unsigned", i+1);
diff --git a/platform/win32/libpkcs7.vcxproj b/platform/win32/libpkcs7.vcxproj
index 33a4af2f6..25e806f2b 100644
--- a/platform/win32/libpkcs7.vcxproj
+++ b/platform/win32/libpkcs7.vcxproj
@@ -416,14 +416,12 @@
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
- <ClInclude Include="..\..\include\mupdf\helpers\pkcs7-check.h" />
<ClInclude Include="..\..\include\mupdf\helpers\pkcs7-openssl.h" />
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\..\source\helpers\pkcs7\pkcs7-check.c" />
<ClCompile Include="..\..\source\helpers\pkcs7\pkcs7-openssl.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/platform/win32/libpkcs7.vcxproj.filters b/platform/win32/libpkcs7.vcxproj.filters
index f2c15a32d..e6d74db17 100644
--- a/platform/win32/libpkcs7.vcxproj.filters
+++ b/platform/win32/libpkcs7.vcxproj.filters
@@ -9,17 +9,11 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="..\..\include\mupdf\helpers\pkcs7-check.h">
- <Filter>include</Filter>
- </ClInclude>
<ClInclude Include="..\..\include\mupdf\helpers\pkcs7-openssl.h">
<Filter>include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\..\source\helpers\pkcs7\pkcs7-check.c">
- <Filter>source</Filter>
- </ClCompile>
<ClCompile Include="..\..\source\helpers\pkcs7\pkcs7-openssl.c">
<Filter>source</Filter>
</ClCompile>
diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c
index fa201c600..1145431ac 100644
--- a/platform/x11/pdfapp.c
+++ b/platform/x11/pdfapp.c
@@ -1,6 +1,5 @@
#include "pdfapp.h"
#include "curl_stream.h"
-#include "mupdf/helpers/pkcs7-check.h"
#include "mupdf/helpers/pkcs7-openssl.h"
#include <string.h>
diff --git a/source/helpers/pkcs7/pkcs7-check.c b/source/helpers/pkcs7/pkcs7-check.c
index 9a20b9c38..e69de29bb 100644
--- a/source/helpers/pkcs7/pkcs7-check.c
+++ b/source/helpers/pkcs7/pkcs7-check.c
@@ -1,212 +0,0 @@
-#include "mupdf/fitz.h"
-#include "mupdf/pdf.h"
-
-#include "mupdf/helpers/pkcs7-check.h"
-
-char *pdf_signature_error_description(pdf_signature_error err)
-{
- switch (err)
- {
- case PDF_SIGNATURE_ERROR_OKAY:
- return "OK";
- case PDF_SIGNATURE_ERROR_NO_SIGNATURES:
- return "No signatures.";
- case PDF_SIGNATURE_ERROR_NO_CERTIFICATE:
- return "No certificate.";
- case PDF_SIGNATURE_ERROR_DIGEST_FAILURE:
- return "Signature invalidated by change to document.";
- case PDF_SIGNATURE_ERROR_SELF_SIGNED:
- return "Self-signed certificate.";
- case PDF_SIGNATURE_ERROR_SELF_SIGNED_IN_CHAIN:
- return "Self-signed certificate in chain.";
- case PDF_SIGNATURE_ERROR_NOT_TRUSTED:
- return "Certificate not trusted.";
- default:
- case PDF_SIGNATURE_ERROR_UNKNOWN:
- return "Unknown error.";
- }
-}
-
-#ifdef HAVE_LIBCRYPTO
-#include "mupdf/helpers/pkcs7-openssl.h"
-#include <string.h>
-
-static void pdf_format_designated_name(pdf_pkcs7_designated_name *name, char *buf, size_t 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_signature_designated_name(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char *buf, size_t buflen)
-{
- char *contents = NULL;
- size_t contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
- pdf_pkcs7_designated_name *name = NULL;
- fz_try(ctx)
- {
- name = pkcs7_openssl_designated_name(ctx, contents, contents_len);
- if (name)
- {
- pdf_format_designated_name(name, buf, buflen);
- pkcs7_openssl_drop_designated_name(ctx, name);
- }
- else if (buflen > 0)
- buf[0] = '\0';
- }
- fz_always(ctx)
- fz_free(ctx, contents);
- fz_catch(ctx)
- fz_rethrow(ctx);
-}
-
-pdf_signature_error pdf_check_digest(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
-{
- pdf_signature_error err;
- fz_stream *bytes = NULL;
- char *contents = NULL;
- size_t contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
- fz_var(err);
- fz_var(bytes);
- fz_try(ctx)
- {
- bytes = pdf_signature_hash_bytes(ctx, doc, signature);
- err = pkcs7_openssl_check_digest(ctx, bytes, contents, contents_len);
- }
- fz_always(ctx)
- {
- fz_drop_stream(ctx, bytes);
- fz_free(ctx, contents);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-
- return err;
-}
-
-pdf_signature_error pdf_check_certificate(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
-{
- char *contents = NULL;
- size_t contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
- pdf_signature_error result;
- fz_try(ctx)
- result = pkcs7_openssl_check_certificate(contents, contents_len);
- fz_always(ctx)
- fz_free(ctx, contents);
- fz_catch(ctx)
- fz_rethrow(ctx);
- return result;
-}
-
-int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char *ebuf, size_t ebufsize)
-{
- int res = 0;
-
- if (pdf_xref_obj_is_unsaved_signature(doc, signature))
- {
- fz_strlcpy(ebuf, "Signed but document yet to be saved.", ebufsize);
- if (ebufsize > 0)
- ebuf[ebufsize-1] = 0;
- return 0;
- }
-
- fz_var(res);
- fz_try(ctx)
- {
- if (pdf_signature_is_signed(ctx, doc, signature))
- {
- pdf_signature_error err;
-
- err = pdf_check_digest(ctx, doc, signature);
- if (err == PDF_SIGNATURE_ERROR_OKAY)
- err = pdf_check_certificate(ctx, doc, signature);
-
- fz_strlcpy(ebuf, pdf_signature_error_description(err), ebufsize);
- res = (err == PDF_SIGNATURE_ERROR_OKAY);
-
- switch (err)
- {
- case PDF_SIGNATURE_ERROR_SELF_SIGNED:
- case PDF_SIGNATURE_ERROR_SELF_SIGNED_IN_CHAIN:
- case PDF_SIGNATURE_ERROR_NOT_TRUSTED:
- {
- size_t len;
- fz_strlcat(ebuf, " (", ebufsize);
- len = strlen(ebuf);
- pdf_signature_designated_name(ctx, doc, signature, ebuf + len, ebufsize - len);
- fz_strlcat(ebuf, ")", ebufsize);
- }
- break;
- default:
- break;
- }
- }
- else
- {
- res = 0;
- fz_strlcpy(ebuf, "Not signed.", ebufsize);
- }
- }
- fz_catch(ctx)
- {
- res = 0;
- fz_strlcpy(ebuf, fz_caught_message(ctx), ebufsize);
- }
-
- if (ebufsize > 0)
- ebuf[ebufsize-1] = 0;
-
- return res;
-}
-
-int pdf_supports_signatures(fz_context *ctx)
-{
- return 1;
-}
-
-#else
-
-void pdf_signature_designated_name(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char *buf, size_t buflen)
-{
- fz_throw(ctx, FZ_ERROR_GENERIC, "No OpenSSL support.");
-}
-
-pdf_signature_error pdf_check_digest(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
-{
- fz_throw(ctx, FZ_ERROR_GENERIC, "No OpenSSL support.");
- return 0;
-}
-
-pdf_signature_error pdf_check_certificate(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
-{
- fz_throw(ctx, FZ_ERROR_GENERIC, "No OpenSSL support.");
- return 0;
-}
-
-
-int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char *ebuf, size_t ebufsize)
-{
- fz_strlcpy(ebuf, "No digital signing support in this build", ebufsize);
- return 0;
-}
-
-int pdf_supports_signatures(fz_context *ctx)
-{
- return 0;
-}
-
-#endif
diff --git a/source/helpers/pkcs7/pkcs7-openssl.c b/source/helpers/pkcs7/pkcs7-openssl.c
index 68f74a6c0..7f09c6ba4 100644
--- a/source/helpers/pkcs7/pkcs7-openssl.c
+++ b/source/helpers/pkcs7/pkcs7-openssl.c
@@ -5,32 +5,14 @@
#ifndef HAVE_LIBCRYPTO
-pdf_signature_error
-pkcs7_openssl_check_digest(fz_context *ctx, fz_stream *stm, char *sig, size_t sig_len)
-{
- return PDF_SIGNATURE_ERROR_UNKNOWN;
-}
-
-/* Check a signature's certificate is trusted */
-pdf_signature_error
-pkcs7_openssl_check_certificate(char *sig, size_t sig_len)
-{
- return PDF_SIGNATURE_ERROR_UNKNOWN;
-}
-
-pdf_pkcs7_designated_name *
-pkcs7_openssl_designated_name(fz_context *ctx, char *sig, size_t sig_len)
-{
- return NULL;
-}
-
-void
-pkcs7_openssl_drop_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *dn)
+pdf_pkcs7_signer *
+pkcs7_openssl_read_pfx(fz_context *ctx, const char *pfile, const char *pw)
{
+ fz_throw(ctx, FZ_ERROR_GENERIC, "No OpenSSL support.");
}
-pdf_pkcs7_signer *
-pkcs7_openssl_read_pfx(fz_context *ctx, const char *pfile, const char *pw)
+pdf_pkcs7_verifier *
+pkcs7_openssl_new_verifier(fz_context *ctx)
{
fz_throw(ctx, FZ_ERROR_GENERIC, "No OpenSSL support.");
}
@@ -437,7 +419,8 @@ exit:
return res;
}
-pdf_signature_error pkcs7_openssl_check_digest(fz_context *ctx, fz_stream *stm, char *sig, size_t sig_len)
+static pdf_signature_error
+check_digest(fz_context *ctx, pdf_pkcs7_verifier *verifier, fz_stream *stm, unsigned char *sig, size_t sig_len)
{
PKCS7 *pk7sig = NULL;
BIO *bsig = NULL;
@@ -466,7 +449,8 @@ exit:
return res;
}
-pdf_signature_error pkcs7_openssl_check_certificate(char *sig, size_t sig_len)
+static pdf_signature_error
+check_certificate(fz_context *ctx, pdf_pkcs7_verifier *verifier, unsigned char *sig, size_t sig_len)
{
PKCS7 *pk7sig = NULL;
PKCS7 *pk7cert = NULL;
@@ -526,25 +510,18 @@ typedef struct pdf_pkcs7_designated_name_openssl_s
char buf[8192];
} pdf_pkcs7_designated_name_openssl;
-void pkcs7_openssl_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;
-static void signer_drop_designated_name(pdf_pkcs7_signer *signer, pdf_pkcs7_designated_name *dn)
+typedef struct
{
- openssl_signer *osigner = (openssl_signer *)signer;
- fz_free(osigner->ctx, dn);
-}
+ pdf_pkcs7_verifier base;
+} openssl_verifier;
static void add_from_bags(X509 **pX509, EVP_PKEY **pPkey, const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pw);
@@ -607,62 +584,80 @@ 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);
}
-static pdf_pkcs7_signer *keep_signer(pdf_pkcs7_signer *signer)
+static pdf_pkcs7_signer *keep_signer(fz_context *ctx, pdf_pkcs7_signer *signer)
{
openssl_signer *osigner = (openssl_signer *)signer;
- return fz_keep_imp(osigner->ctx, osigner, &osigner->refs);
+ return fz_keep_imp(ctx, osigner, &osigner->refs);
}
-static void drop_signer(pdf_pkcs7_signer *signer)
+static void drop_signer(fz_context *ctx, pdf_pkcs7_signer *signer)
{
openssl_signer *osigner = (openssl_signer *)signer;
- if (fz_drop_imp(osigner->ctx, osigner, &osigner->refs))
+ if (fz_drop_imp(ctx, osigner, &osigner->refs))
{
X509_free(osigner->x509);
EVP_PKEY_free(osigner->pkey);
- fz_free(osigner->ctx, osigner);
+ fz_free(ctx, osigner);
}
}
+static char *x509_get_name_entry_string(fz_context *ctx, X509_NAME *name, int nid)
+{
+ int idx = X509_NAME_get_index_by_NID(name, nid, -1);
+ X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, idx);
+ ASN1_STRING *data = X509_NAME_ENTRY_get_data(entry);
+ return fz_strdup(ctx, (const char *)ASN1_STRING_get0_data(data));
+}
+
static pdf_pkcs7_designated_name *x509_designated_name(fz_context *ctx, X509 *x509)
{
- pdf_pkcs7_designated_name_openssl *dn;
- char *p;
+ pdf_pkcs7_designated_name *dn = fz_malloc_struct(ctx, pdf_pkcs7_designated_name);
fz_try(ctx)
- dn = fz_malloc_struct(ctx, pdf_pkcs7_designated_name_openssl);
+ {
+ X509_NAME *subj = X509_get_subject_name(x509);
+ dn->cn = x509_get_name_entry_string(ctx, subj, NID_commonName);
+ dn->o = x509_get_name_entry_string(ctx, subj, NID_organizationName);
+ dn->ou = x509_get_name_entry_string(ctx, subj, NID_organizationalUnitName);
+ dn->email = x509_get_name_entry_string(ctx, subj, NID_pkcs9_emailAddress);
+ dn->c = x509_get_name_entry_string(ctx, subj, NID_countryName);
+ }
fz_catch(ctx)
- return NULL;
-
- X509_NAME_oneline(X509_get_subject_name(x509), dn->buf, sizeof(dn->buf));
- p = strstr(dn->buf, "/CN=");
- if (p) dn->base.cn = p+4;
- p = strstr(dn->buf, "/O=");
- if (p) dn->base.o = p+3;
- p = strstr(dn->buf, "/OU=");
- if (p) dn->base.ou = p+4;
- p = strstr(dn->buf, "/emailAddress=");
- if (p) dn->base.email = p+14;
- p = strstr(dn->buf, "/C=");
- if (p) dn->base.c = p+3;
-
- for (p = dn->buf; *p; p++)
- if (*p == '/')
- *p = 0;
+ {
+ pdf_signature_drop_designated_name(ctx, dn);
+ fz_rethrow(ctx);
+ }
return (pdf_pkcs7_designated_name *)dn;
}
-static pdf_pkcs7_designated_name *signer_designated_name(pdf_pkcs7_signer *signer)
+static pdf_pkcs7_designated_name *signer_designated_name(fz_context *ctx, pdf_pkcs7_signer *signer)
{
openssl_signer *osigner = (openssl_signer *)signer;
- return x509_designated_name(osigner->ctx, osigner->x509);
+ X509 *x509 = osigner->x509;
+ pdf_pkcs7_designated_name *dn = fz_malloc_struct(ctx, pdf_pkcs7_designated_name);
+
+ fz_try(ctx)
+ {
+ X509_NAME *subj = X509_get_subject_name(x509);
+ dn->cn = x509_get_name_entry_string(ctx, subj, NID_commonName);
+ dn->o = x509_get_name_entry_string(ctx, subj, NID_organizationName);
+ dn->ou = x509_get_name_entry_string(ctx, subj, NID_organizationalUnitName);
+ dn->email = x509_get_name_entry_string(ctx, subj, NID_pkcs9_emailAddress);
+ dn->c = x509_get_name_entry_string(ctx, subj, NID_countryName);
+ }
+ fz_catch(ctx)
+ {
+ pdf_signature_drop_designated_name(ctx, dn);
+ fz_rethrow(ctx);
+ }
+
+ return dn;
}
-static int signer_create_digest(pdf_pkcs7_signer *signer, fz_stream *in, unsigned char *digest, size_t *digest_len)
+static int signer_create_digest(fz_context *ctx, pdf_pkcs7_signer *signer, fz_stream *in, unsigned char *digest, size_t digest_len)
{
openssl_signer *osigner = (openssl_signer *)signer;
- fz_context *ctx = osigner->ctx;
int res = 0;
BIO *bdata = NULL;
BIO *bp7in = NULL;
@@ -719,14 +714,13 @@ static int signer_create_digest(pdf_pkcs7_signer *signer, fz_stream *in, unsigne
goto exit;
p7_len = (size_t)BIO_get_mem_data(bp7, &p7_ptr);
- if (digest && p7_len > *digest_len)
+ if (digest && p7_len > digest_len)
goto exit;
if (digest)
memcpy(digest, p7_ptr, p7_len);
- *digest_len = p7_len;
- res = 1;
+ res = p7_len;
exit:
BIO_free(bp7);
@@ -737,13 +731,13 @@ exit:
return res;
}
-static size_t max_digest_size(pdf_pkcs7_signer *signer)
+static size_t max_digest_size(fz_context *ctx, pdf_pkcs7_signer *signer)
{
/* Perform a test digest generation to find the required size. Size
* is assumed independent of data being hashed */
size_t digest_len = 0;
- signer_create_digest(signer, NULL, NULL, &digest_len);
+ signer_create_digest(ctx, signer, NULL, NULL, digest_len);
return digest_len;
}
@@ -764,11 +758,9 @@ pdf_pkcs7_signer *pkcs7_openssl_read_pfx(fz_context *ctx, const char *pfile, con
signer = fz_malloc_struct(ctx, openssl_signer);
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.get_signing_name = signer_designated_name;
signer->base.max_digest_size = max_digest_size;
signer->base.create_digest = signer_create_digest;
- signer->ctx = ctx;
signer->refs = 1;
OpenSSL_add_all_algorithms();
@@ -834,14 +826,14 @@ pdf_pkcs7_signer *pkcs7_openssl_read_pfx(fz_context *ctx, const char *pfile, con
}
fz_catch(ctx)
{
- drop_signer(&signer->base);
+ drop_signer(ctx, &signer->base);
fz_rethrow(ctx);
}
return &signer->base;
}
-pdf_pkcs7_designated_name *pkcs7_openssl_designated_name(fz_context *ctx, char *sig, size_t sig_len)
+pdf_pkcs7_designated_name *get_signatory(fz_context *ctx, pdf_pkcs7_verifier *verifier, unsigned char *sig, size_t sig_len)
{
pdf_pkcs7_designated_name *name = NULL;
PKCS7 *pk7sig = NULL;
@@ -863,7 +855,14 @@ pdf_pkcs7_designated_name *pkcs7_openssl_designated_name(fz_context *ctx, char *
x509 = pk7_signer(pk7_certs(pk7sig), sk_PKCS7_SIGNER_INFO_value(sk, 0));
- name = x509_designated_name(ctx, x509);
+ fz_try(ctx)
+ name = x509_designated_name(ctx, x509);
+ fz_catch(ctx)
+ {
+ PKCS7_free(pk7sig);
+ BIO_free(bsig);
+ fz_rethrow(ctx);
+ }
exit:
PKCS7_free(pk7sig);
@@ -872,4 +871,24 @@ exit:
return name;
}
+static void
+drop_openssl_verifier(fz_context *ctx, pdf_pkcs7_verifier *verifier)
+{
+ fz_free(ctx, verifier);
+}
+
+pdf_pkcs7_verifier *
+pkcs7_openssl_new_verifier(fz_context *ctx)
+{
+ openssl_verifier *verifier = NULL;
+
+ verifier = fz_malloc_struct(ctx, openssl_verifier);
+ verifier->base.drop = drop_openssl_verifier;
+ verifier->base.check_digest = check_digest;
+ verifier->base.check_certificate = check_certificate;
+ verifier->base.get_signatory = get_signatory;
+
+ return &verifier->base;
+}
+
#endif
diff --git a/source/pdf/pdf-form.c b/source/pdf/pdf-form.c
index 415c57776..0b889bb72 100644
--- a/source/pdf/pdf-form.c
+++ b/source/pdf/pdf-form.c
@@ -1629,7 +1629,7 @@ void pdf_signature_set_value(fz_context *ctx, pdf_document *doc, pdf_obj *field,
indv = pdf_new_indirect(ctx, doc, vnum, 0);
pdf_dict_put_drop(ctx, field, PDF_NAME(V), indv);
- max_digest_size = signer->max_digest_size(signer);
+ max_digest_size = signer->max_digest_size(ctx, signer);
fz_var(v);
fz_var(o);
diff --git a/source/pdf/pdf-signature.c b/source/pdf/pdf-signature.c
index 0804cec7b..6b192c96b 100644
--- a/source/pdf/pdf-signature.c
+++ b/source/pdf/pdf-signature.c
@@ -29,7 +29,7 @@ void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, size
fz_try(ctx)
{
- int i, res;
+ int i;
size_t z;
brange = fz_calloc(ctx, brange_len, sizeof(*brange));
@@ -44,9 +44,7 @@ void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, size
digest_len = (hexdigest_length - 2) / 2;
digest = fz_malloc(ctx, digest_len);
- res = signer->create_digest(signer, in, digest, &digest_len);
- if (!res)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pdf_pkcs7_create_digest failed");
+ digest_len = signer->create_digest(ctx, signer, in, digest, digest_len);
fz_drop_stream(ctx, in);
in = NULL;
@@ -171,6 +169,9 @@ void pdf_sign_signature(fz_context *ctx, pdf_widget *widget, pdf_pkcs7_signer *s
fz_buffer *fzbuf = NULL;
pdf_document *doc = widget->page->doc;
+ fz_var(dn);
+ fz_var(fzbuf);
+
fz_try(ctx)
{
const char *dn_str;
@@ -200,7 +201,7 @@ void pdf_sign_signature(fz_context *ctx, pdf_widget *widget, pdf_pkcs7_signer *s
/* Create an appearance stream only if the signature is intended to be visible */
if (!fz_is_empty_rect(rect))
{
- dn = signer->designated_name(signer);
+ dn = signer->get_signing_name(ctx, signer);
if (!dn || !dn->cn)
fz_throw(ctx, FZ_ERROR_GENERIC, "Certificate has no common name");
@@ -236,8 +237,8 @@ void pdf_sign_signature(fz_context *ctx, pdf_widget *widget, pdf_pkcs7_signer *s
}
fz_always(ctx)
{
- signer->drop_designated_name(signer, dn);
fz_drop_buffer(ctx, fzbuf);
+ pdf_signature_drop_designated_name(ctx, dn);
}
fz_catch(ctx)
{
@@ -260,3 +261,203 @@ void pdf_clear_signature(fz_context *ctx, pdf_widget *widget)
pdf_update_signature_appearance(ctx, widget, NULL, NULL, NULL);
}
+
+void pdf_drop_signer(fz_context *ctx, pdf_pkcs7_signer *signer)
+{
+ if (signer)
+ signer->drop(ctx, signer);
+}
+
+void pdf_drop_verifier(fz_context *ctx, pdf_pkcs7_verifier *verifier)
+{
+ if (verifier)
+ verifier->drop(ctx, verifier);
+}
+
+char *pdf_signature_error_description(pdf_signature_error err)
+{
+ switch (err)
+ {
+ case PDF_SIGNATURE_ERROR_OKAY:
+ return "OK";
+ case PDF_SIGNATURE_ERROR_NO_SIGNATURES:
+ return "No signatures.";
+ case PDF_SIGNATURE_ERROR_NO_CERTIFICATE:
+ return "No certificate.";
+ case PDF_SIGNATURE_ERROR_DIGEST_FAILURE:
+ return "Signature invalidated by change to document.";
+ case PDF_SIGNATURE_ERROR_SELF_SIGNED:
+ return "Self-signed certificate.";
+ case PDF_SIGNATURE_ERROR_SELF_SIGNED_IN_CHAIN:
+ return "Self-signed certificate in chain.";
+ case PDF_SIGNATURE_ERROR_NOT_TRUSTED:
+ return "Certificate not trusted.";
+ default:
+ case PDF_SIGNATURE_ERROR_UNKNOWN:
+ return "Unknown error.";
+ }
+}
+
+void pdf_signature_drop_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *dn)
+{
+ if (dn)
+ {
+ fz_free(ctx, dn->c);
+ fz_free(ctx, dn->email);
+ fz_free(ctx, dn->ou);
+ fz_free(ctx, dn->o);
+ fz_free(ctx, dn->cn);
+ fz_free(ctx, dn);
+ }
+}
+
+char *pdf_signature_format_designated_name(fz_context *ctx, pdf_pkcs7_designated_name *name)
+{
+ const char *parts[] = {
+ "CN=", name->cn,
+ ", O=", name->o,
+ ", OU=", name->ou,
+ ", emailAddress=", name->email,
+ ", C=", name->c};
+ int len = 1;
+ char *s;
+ int i;
+
+ for (i = 0; i < (int)nelem(parts); i++)
+ if (parts[i])
+ len += strlen(parts[i]);
+
+ s = fz_malloc(ctx, len);
+ s[0] = '\0';
+
+ for (i = 0; i < (int)nelem(parts); i++)
+ if (parts[i])
+ fz_strlcat(s, parts[i], len);
+
+ return s;
+}
+
+pdf_pkcs7_designated_name *pdf_signature_get_signatory(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature)
+{
+ char *contents = NULL;
+ int contents_len = 0;
+ pdf_pkcs7_designated_name *dn;
+
+ contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
+
+ fz_try(ctx)
+ dn = verifier->get_signatory(ctx, verifier, (unsigned char *)contents, contents_len);
+ fz_always(ctx)
+ fz_free(ctx, contents);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+
+ return dn;
+}
+
+pdf_signature_error pdf_check_digest(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature)
+{
+ pdf_signature_error result = PDF_SIGNATURE_ERROR_UNKNOWN;
+ fz_stream *bytes = NULL;
+ char *contents = NULL;
+ int contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
+ fz_var(bytes);
+ fz_try(ctx)
+ {
+ bytes = pdf_signature_hash_bytes(ctx, doc, signature);
+ result = verifier->check_digest(ctx, verifier, bytes, (unsigned char *)contents, contents_len);
+ }
+ fz_always(ctx)
+ {
+ fz_drop_stream(ctx, bytes);
+ fz_free(ctx, contents);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+
+ return result;
+}
+
+pdf_signature_error pdf_check_certificate(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature)
+{
+ char *contents = NULL;
+ size_t contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
+ pdf_signature_error result = PDF_SIGNATURE_ERROR_UNKNOWN;
+ fz_try(ctx)
+ result = verifier->check_certificate(ctx, verifier, (unsigned char *)contents, contents_len);
+ fz_always(ctx)
+ fz_free(ctx, contents);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+ return result;
+}
+
+int pdf_check_signature(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature, char *ebuf, size_t ebufsize)
+{
+ int res = 0;
+
+ if (pdf_xref_obj_is_unsaved_signature(doc, signature))
+ {
+ fz_strlcpy(ebuf, "Signed but document yet to be saved.", ebufsize);
+ if (ebufsize > 0)
+ ebuf[ebufsize-1] = 0;
+ return 0;
+ }
+
+ fz_var(res);
+ fz_try(ctx)
+ {
+ if (pdf_signature_is_signed(ctx, doc, signature))
+ {
+ pdf_signature_error err;
+
+ err = pdf_check_digest(ctx, verifier, doc, signature);
+ if (err == PDF_SIGNATURE_ERROR_OKAY)
+ err = pdf_check_certificate(ctx, verifier, doc, signature);
+
+ fz_strlcpy(ebuf, pdf_signature_error_description(err), ebufsize);
+ res = (err == PDF_SIGNATURE_ERROR_OKAY);
+
+ switch (err)
+ {
+ case PDF_SIGNATURE_ERROR_SELF_SIGNED:
+ case PDF_SIGNATURE_ERROR_SELF_SIGNED_IN_CHAIN:
+ case PDF_SIGNATURE_ERROR_NOT_TRUSTED:
+ {
+ pdf_pkcs7_designated_name *dn;
+ char *s;
+
+ fz_strlcat(ebuf, " (", ebufsize);
+
+ dn = pdf_signature_get_signatory(ctx, verifier, doc, signature);
+ s = pdf_signature_format_designated_name(ctx, dn);
+ pdf_signature_drop_designated_name(ctx, dn);
+
+ fz_strlcat(ebuf, s, ebufsize);
+ fz_free(ctx, s);
+ fz_strlcat(ebuf, ")", ebufsize);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else
+ {
+ res = 0;
+ fz_strlcpy(ebuf, "Not signed.", ebufsize);
+ }
+ }
+ 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-write.c b/source/pdf/pdf-write.c
index 999266e52..107961fab 100644
--- a/source/pdf/pdf-write.c
+++ b/source/pdf/pdf-write.c
@@ -2815,7 +2815,7 @@ static void complete_signatures(fz_context *ctx, pdf_document *doc, pdf_write_st
for (usig = xref->unsaved_sigs; usig; usig = usig->next)
{
- size_t size = usig->signer->max_digest_size(usig->signer);
+ size_t size = usig->signer->max_digest_size(ctx, usig->signer);
buf_size = fz_maxz(buf_size, size);
}
@@ -2896,7 +2896,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);
- usig->signer->drop(usig->signer);
+ pdf_drop_signer(ctx, usig->signer);
fz_free(ctx, usig);
}
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
index d67b8990d..4e4ca514d 100644
--- a/source/pdf/pdf-xref.c
+++ b/source/pdf/pdf-xref.c
@@ -60,7 +60,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);
- usig->signer->drop(usig->signer);
+ pdf_drop_signer(ctx, usig->signer);
fz_free(ctx, usig);
}
}
@@ -422,7 +422,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 = signer->keep(signer);
+ unsaved_sig->signer = signer->keep(ctx, signer);
unsaved_sig->next = NULL;
if (xref->unsaved_sigs_end == NULL)
xref->unsaved_sigs_end = &xref->unsaved_sigs;
diff --git a/source/tools/murun.c b/source/tools/murun.c
index d35946b45..4d86da79a 100644
--- a/source/tools/murun.c
+++ b/source/tools/murun.c
@@ -2,7 +2,6 @@
#if FZ_ENABLE_PDF
#include "mupdf/pdf.h"
-#include "mupdf/helpers/pkcs7-check.h"
#include "mupdf/helpers/pkcs7-openssl.h"
#endif
@@ -215,9 +214,10 @@ static void ffi_gc_fz_document(js_State *J, void *doc)
static void ffi_gc_pdf_pkcs7_signer(js_State *J, void *signer_)
{
+ fz_context *ctx = js_getcontext(J);
pdf_pkcs7_signer *signer = (pdf_pkcs7_signer *)signer_;
if (signer)
- signer->drop(signer);
+ signer->drop(ctx, signer);
}
static void ffi_gc_fz_page(js_State *J, void *page)
@@ -4961,6 +4961,7 @@ static void ffi_PDFWidget_sign(js_State *J)
fz_context *ctx = js_getcontext(J);
pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
pdf_pkcs7_signer *signer = js_touserdata(J, 1, "pdf_pkcs7_signer");
+
fz_try(ctx)
pdf_sign_signature(ctx, widget, signer);
fz_catch(ctx)
diff --git a/source/tools/pdfsign.c b/source/tools/pdfsign.c
index ae5f8fb8a..3adbbdb28 100644
--- a/source/tools/pdfsign.c
+++ b/source/tools/pdfsign.c
@@ -4,7 +4,6 @@
#include "mupdf/fitz.h"
#include "mupdf/pdf.h"
-#include "mupdf/helpers/pkcs7-check.h"
#include "mupdf/helpers/pkcs7-openssl.h"
#include <string.h>
@@ -36,9 +35,11 @@ static void usage(void)
static void verify_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
{
- char name[500];
+ char *name;
pdf_signature_error err;
+ pdf_pkcs7_verifier *verifier;
int edits;
+ pdf_pkcs7_designated_name *dn = NULL;
printf("verifying signature %d\n", pdf_to_num(ctx, signature));
@@ -48,18 +49,23 @@ static void verify_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signat
return;
}
- pdf_signature_designated_name(ctx, doc, signature, name, sizeof name);
- printf(" Designated name: %s\n", name);
-
- err = pdf_check_certificate(ctx, doc, signature);
- if (err)
- printf(" Certificate error: %s\n", pdf_signature_error_description(err));
- else
- printf(" Certificate is trusted.\n");
-
+ verifier = pkcs7_openssl_new_verifier(ctx);
+ fz_var(dn);
fz_try(ctx)
{
- err = pdf_check_digest(ctx, doc, signature);
+ dn = pdf_signature_get_signatory(ctx, verifier, doc, signature);
+ name = pdf_signature_format_designated_name(ctx, dn);
+
+ printf(" Designated name: %s\n", name);
+ fz_free(ctx, name);
+
+ err = pdf_check_certificate(ctx, verifier, doc, signature);
+ if (err)
+ printf(" Certificate error: %s\n", pdf_signature_error_description(err));
+ else
+ printf(" Certificate is trusted.\n");
+
+ err = pdf_check_digest(ctx, verifier, doc, signature);
edits = pdf_signature_incremental_change_since_signing(ctx, doc, signature);
if (err)
printf(" Digest error: %s\n", pdf_signature_error_description(err));
@@ -68,8 +74,13 @@ static void verify_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signat
else
printf(" The document is unchanged since signing.\n");
}
+ fz_always(ctx)
+ {
+ pdf_signature_drop_designated_name(ctx, dn);
+ pdf_drop_verifier(ctx, verifier);
+ }
fz_catch(ctx)
- printf(" Digest error: %s\n", fz_caught_message(ctx));
+ printf(" Verification error: %s\n", fz_caught_message(ctx));
}
static void clear_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
@@ -125,8 +136,7 @@ static void sign_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signatur
fz_always(ctx)
{
fz_drop_page(ctx, (fz_page*)page);
- if (signer)
- signer->drop(signer);
+ pdf_drop_signer(ctx, signer);
}
fz_catch(ctx)
fz_rethrow(ctx);
@@ -135,9 +145,20 @@ static void sign_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signatur
static void list_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
{
- char name[500];
- pdf_signature_designated_name(ctx, doc, signature, name, sizeof name);
- printf("%5d: signature name: %s\n", pdf_to_num(ctx, signature), name);
+ pdf_pkcs7_designated_name *dn;
+ pdf_pkcs7_verifier *verifier;
+ char *s;
+
+ verifier = pkcs7_openssl_new_verifier(ctx);
+
+ dn = pdf_signature_get_signatory(ctx, verifier, doc, signature);
+ s = pdf_signature_format_designated_name(ctx, dn);
+ pdf_signature_drop_designated_name(ctx, dn);
+
+ pdf_drop_verifier(ctx, verifier);
+
+ printf("%5d: signature name: %s\n", pdf_to_num(ctx, signature), s);
+ fz_free(ctx, s);
}
static void process_field(fz_context *ctx, pdf_document *doc, pdf_obj *field)