diff options
author | Sebastian Rasmussen <sebras@gmail.com> | 2020-04-04 14:34:27 +0100 |
---|---|---|
committer | Robin Watts <Robin.Watts@artifex.com> | 2020-04-07 17:55:00 +0100 |
commit | 3f9ee8f4dfa03e9680cf0777f1518e305cb48c09 (patch) | |
tree | 1351308ab1c02b5188949b0816eb51a281d1db61 | |
parent | 4c420da4ed846918a3de4e0912fd95cffeba7c7d (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-- | Makefile | 4 | ||||
-rw-r--r-- | include/mupdf/helpers/pkcs7-check.h | 18 | ||||
-rw-r--r-- | include/mupdf/helpers/pkcs7-openssl.h | 5 | ||||
-rw-r--r-- | include/mupdf/pdf/crypt.h | 1 | ||||
-rw-r--r-- | include/mupdf/pdf/document.h | 54 | ||||
-rw-r--r-- | include/mupdf/pdf/form.h | 84 | ||||
-rw-r--r-- | platform/gl/gl-form.c | 25 | ||||
-rw-r--r-- | platform/gl/gl-main.c | 21 | ||||
-rw-r--r-- | platform/win32/libpkcs7.vcxproj | 4 | ||||
-rw-r--r-- | platform/win32/libpkcs7.vcxproj.filters | 6 | ||||
-rw-r--r-- | platform/x11/pdfapp.c | 1 | ||||
-rw-r--r-- | source/helpers/pkcs7/pkcs7-check.c | 212 | ||||
-rw-r--r-- | source/helpers/pkcs7/pkcs7-openssl.c | 169 | ||||
-rw-r--r-- | source/pdf/pdf-form.c | 2 | ||||
-rw-r--r-- | source/pdf/pdf-signature.c | 213 | ||||
-rw-r--r-- | source/pdf/pdf-write.c | 4 | ||||
-rw-r--r-- | source/pdf/pdf-xref.c | 4 | ||||
-rw-r--r-- | source/tools/murun.c | 5 | ||||
-rw-r--r-- | source/tools/pdfsign.c | 57 |
19 files changed, 466 insertions, 423 deletions
@@ -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) |