| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668 |
- // Copyright (C) 2004-2025 Artifex Software, Inc.
- //
- // This file is part of MuPDF.
- //
- // MuPDF is free software: you can redistribute it and/or modify it under the
- // terms of the GNU Affero General Public License as published by the Free
- // Software Foundation, either version 3 of the License, or (at your option)
- // any later version.
- //
- // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
- // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- // details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
- //
- // Alternative licensing terms are available from the licensor.
- // For commercial licensing, see <https://www.artifex.com/> or contact
- // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
- // CA 94129, USA, for further information.
- #include "mupdf/fitz.h"
- #include "pdf-annot-imp.h"
- #include <string.h>
- #include <time.h>
- enum
- {
- PDF_SIGFLAGS_SIGSEXIST = 1,
- PDF_SIGFLAGS_APPENDONLY = 2
- };
- static void
- begin_widget_op(fz_context *ctx, pdf_annot *annot, const char *op)
- {
- if (!annot->page)
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
- pdf_begin_operation(ctx, annot->page->doc, op);
- }
- static void
- end_widget_op(fz_context *ctx, pdf_annot *annot)
- {
- pdf_end_operation(ctx, annot->page->doc);
- }
- static void
- abandon_widget_op(fz_context *ctx, pdf_annot *annot)
- {
- pdf_abandon_operation(ctx, annot->page->doc);
- }
- void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, pdf_obj *field, size_t hexdigest_offset, size_t hexdigest_length, pdf_pkcs7_signer *signer)
- {
- fz_stream *stm = NULL;
- fz_stream *in = NULL;
- fz_range *brange = NULL;
- int brange_len = pdf_array_len(ctx, byte_range)/2;
- unsigned char *digest = NULL;
- size_t digest_len;
- pdf_obj *v = pdf_dict_get(ctx, field, PDF_NAME(V));
- size_t len;
- char *cstr = NULL;
- fz_var(stm);
- fz_var(in);
- fz_var(brange);
- fz_var(digest);
- fz_var(cstr);
- if (hexdigest_length < 4)
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "Bad parameters to pdf_write_digest");
- len = (hexdigest_length - 2) / 2;
- fz_try(ctx)
- {
- int i;
- size_t z;
- brange = fz_calloc(ctx, brange_len, sizeof(*brange));
- for (i = 0; i < brange_len; i++)
- {
- brange[i].offset = pdf_array_get_int(ctx, byte_range, 2*i);
- brange[i].length = pdf_array_get_int(ctx, byte_range, 2*i+1);
- }
- stm = fz_stream_from_output(ctx, out);
- in = fz_open_range_filter(ctx, stm, brange, brange_len);
- digest = fz_malloc(ctx, len);
- digest_len = signer->create_digest(ctx, signer, in, digest, len);
- if (digest_len == 0)
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "signer provided no signature digest");
- if (digest_len > len)
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "signature digest larger than space for digest");
- fz_drop_stream(ctx, in);
- in = NULL;
- fz_drop_stream(ctx, stm);
- stm = NULL;
- fz_seek_output(ctx, out, (int64_t)hexdigest_offset+1, SEEK_SET);
- cstr = fz_malloc(ctx, len);
- for (z = 0; z < len; z++)
- {
- int val = z < digest_len ? digest[z] : 0;
- fz_write_printf(ctx, out, "%02x", val);
- cstr[z] = val;
- }
- pdf_dict_put_string(ctx, v, PDF_NAME(Contents), cstr, len);
- }
- fz_always(ctx)
- {
- fz_free(ctx, cstr);
- fz_free(ctx, digest);
- fz_free(ctx, brange);
- fz_drop_stream(ctx, stm);
- fz_drop_stream(ctx, in);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
- }
- typedef struct fieldname_prefix
- {
- struct fieldname_prefix *prev;
- char name[FZ_FLEXIBLE_ARRAY];
- } fieldname_prefix;
- typedef struct
- {
- pdf_locked_fields *locked;
- fieldname_prefix *prefix;
- } sig_locking_data;
- static void
- check_field_locking(fz_context *ctx, pdf_obj *obj, void *data_, pdf_obj **ff)
- {
- fieldname_prefix *prefix = NULL;
- sig_locking_data *data = (sig_locking_data *)data_;
- fz_var(prefix);
- fz_try(ctx)
- {
- const char *name = NULL;
- size_t n = 1;
- pdf_obj *t;
- t = pdf_dict_get(ctx, obj, PDF_NAME(T));
- if (t != NULL)
- {
- name = pdf_to_text_string(ctx, t);
- n += strlen(name);
- }
- if (data->prefix->name[0] && name)
- n += 1;
- if (data->prefix->name[0])
- n += strlen(data->prefix->name);
- prefix = fz_malloc_flexible(ctx, fieldname_prefix, name, n);
- prefix->prev = data->prefix;
- if (data->prefix->name[0])
- strcpy(prefix->name, data->prefix->name);
- if (data->prefix->name[0] && name)
- strcat(prefix->name, ".");
- if (name)
- strcat(prefix->name, name);
- data->prefix = prefix;
- if (pdf_name_eq(ctx, pdf_dict_get(ctx, obj, PDF_NAME(Type)), PDF_NAME(Annot)) &&
- pdf_name_eq(ctx, pdf_dict_get(ctx, obj, PDF_NAME(Subtype)), PDF_NAME(Widget)))
- {
- int flags = pdf_to_int(ctx, *ff);
- if (((flags & PDF_FIELD_IS_READ_ONLY) == 0) && /* Field is not currently locked */
- pdf_is_field_locked(ctx, data->locked, data->prefix->name)) /* Field should be locked */
- pdf_dict_put_int(ctx, obj, PDF_NAME(Ff), flags | PDF_FIELD_IS_READ_ONLY);
- }
- }
- fz_catch(ctx)
- {
- if (prefix)
- {
- data->prefix = prefix->prev;
- fz_free(ctx, prefix);
- }
- fz_rethrow(ctx);
- }
- }
- static void
- pop_field_locking(fz_context *ctx, pdf_obj *obj, void *data_)
- {
- fieldname_prefix *prefix;
- sig_locking_data *data = (sig_locking_data *)data_;
- prefix = data->prefix;
- data->prefix = data->prefix->prev;
- fz_free(ctx, prefix);
- }
- static void enact_sig_locking(fz_context *ctx, pdf_document *doc, pdf_obj *sig)
- {
- pdf_locked_fields *locked = pdf_find_locked_fields_for_sig(ctx, doc, sig);
- pdf_obj *fields;
- static pdf_obj *ff_names[2] = { PDF_NAME(Ff), NULL };
- pdf_obj *ff = NULL;
- static fieldname_prefix null_prefix = { NULL, { 0 } };
- sig_locking_data data = { locked, &null_prefix };
- if (locked == NULL)
- return;
- fz_try(ctx)
- {
- fields = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/AcroForm/Fields");
- pdf_walk_tree(ctx, fields, PDF_NAME(Kids), check_field_locking, pop_field_locking, &data, &ff_names[0], &ff);
- }
- fz_always(ctx)
- pdf_drop_locked_fields(ctx, locked);
- fz_catch(ctx)
- {
- pop_field_locking(ctx, NULL, &data);
- fz_rethrow(ctx);
- }
- }
- void
- pdf_sign_signature_with_appearance(fz_context *ctx, pdf_annot *widget, pdf_pkcs7_signer *signer, int64_t t, fz_display_list *disp_list)
- {
- pdf_document *doc;
- if (pdf_dict_get_inheritable(ctx, widget->obj, PDF_NAME(FT)) != PDF_NAME(Sig))
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
- if (pdf_widget_is_readonly(ctx, widget))
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "Signature is read only, it cannot be signed.");
- begin_widget_op(ctx, widget, "Sign signature");
- doc = widget->page->doc;
- fz_try(ctx)
- {
- pdf_obj *wobj = ((pdf_annot *)widget)->obj;
- pdf_obj *form;
- int sf;
- pdf_dirty_annot(ctx, widget);
- /* Ensure that all fields that will be locked by this signature
- * are marked as ReadOnly. */
- enact_sig_locking(ctx, doc, wobj);
- if (disp_list)
- pdf_set_annot_appearance_from_display_list(ctx, widget, "N", NULL, fz_identity, disp_list);
- /* Update the SigFlags for the document if required */
- form = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/AcroForm");
- if (!form)
- {
- pdf_obj *root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME(Root));
- form = pdf_dict_put_dict(ctx, root, PDF_NAME(AcroForm), 1);
- }
- sf = pdf_to_int(ctx, pdf_dict_get(ctx, form, PDF_NAME(SigFlags)));
- if ((sf & (PDF_SIGFLAGS_SIGSEXIST | PDF_SIGFLAGS_APPENDONLY)) != (PDF_SIGFLAGS_SIGSEXIST | PDF_SIGFLAGS_APPENDONLY))
- pdf_dict_put_int(ctx, form, PDF_NAME(SigFlags), sf | PDF_SIGFLAGS_SIGSEXIST | PDF_SIGFLAGS_APPENDONLY);
- pdf_signature_set_value(ctx, doc, wobj, signer, t);
- end_widget_op(ctx, widget);
- }
- fz_catch(ctx)
- {
- abandon_widget_op(ctx, widget);
- fz_rethrow(ctx);
- }
- }
- static pdf_pkcs7_distinguished_name placeholder_dn = {
- "Your Common Name Here",
- "Organization",
- "Organizational Unit",
- "Email",
- "Country"
- };
- static char *
- pdf_format_signature_info(fz_context *ctx, pdf_pkcs7_signer *signer, int flags, const char *reason, const char *location, int64_t now, char **name)
- {
- pdf_pkcs7_distinguished_name *dn = NULL;
- char *info;
- fz_var(dn);
- fz_try(ctx)
- {
- if (signer)
- dn = signer->get_signing_name(ctx, signer);
- if (!dn)
- dn = &placeholder_dn;
- *name = fz_strdup(ctx, dn->cn ? dn->cn : "Your Common Name Here");
- info = pdf_signature_info(ctx,
- (flags & PDF_SIGNATURE_SHOW_TEXT_NAME) ? *name : NULL,
- (flags & PDF_SIGNATURE_SHOW_DN) ? dn : NULL,
- reason,
- location,
- (flags & PDF_SIGNATURE_SHOW_DATE) ? now : -1,
- (flags & PDF_SIGNATURE_SHOW_LABELS) ? 1 : 0);
- }
- fz_always(ctx)
- {
- if (dn != &placeholder_dn)
- pdf_signature_drop_distinguished_name(ctx, dn);
- }
- fz_catch(ctx)
- fz_rethrow(ctx);
- return info;
- }
- void pdf_sign_signature(fz_context *ctx, pdf_annot *widget,
- pdf_pkcs7_signer *signer,
- int flags,
- fz_image *graphic,
- const char *reason,
- const char *location)
- {
- int logo = flags & PDF_SIGNATURE_SHOW_LOGO;
- fz_rect rect = pdf_annot_rect(ctx, widget);
- fz_text_language lang = pdf_annot_language(ctx, widget);
- #ifdef CLUSTER
- int64_t now = 1112281971; /* release date of MuPDF 0.1 */
- #else
- int64_t now = time(NULL);
- #endif
- char *name = NULL;
- char *info = NULL;
- fz_display_list *dlist = NULL;
- fz_var(dlist);
- fz_var(info);
- fz_var(name);
- /* Create an appearance stream only if the signature is intended to be visible */
- fz_try(ctx)
- {
- if (!fz_is_empty_rect(rect))
- {
- info = pdf_format_signature_info(ctx, signer, flags, reason, location, now, &name);
- if (graphic)
- dlist = pdf_signature_appearance_signed(ctx, rect, lang, graphic, NULL, info, logo);
- else if (flags & PDF_SIGNATURE_SHOW_GRAPHIC_NAME)
- dlist = pdf_signature_appearance_signed(ctx, rect, lang, NULL, name, info, logo);
- else
- dlist = pdf_signature_appearance_signed(ctx, rect, lang, NULL, NULL, info, logo);
- }
- pdf_sign_signature_with_appearance(ctx, widget, signer, now, dlist);
- }
- fz_always(ctx)
- {
- fz_free(ctx, info);
- fz_free(ctx, name);
- fz_drop_display_list(ctx, dlist);
- }
- fz_catch(ctx)
- fz_rethrow(ctx);
- }
- fz_display_list *pdf_preview_signature_as_display_list(fz_context *ctx,
- float w, float h, fz_text_language lang,
- pdf_pkcs7_signer *signer,
- int flags,
- fz_image *graphic,
- const char *reason,
- const char *location)
- {
- int logo = flags & PDF_SIGNATURE_SHOW_LOGO;
- fz_rect rect = fz_make_rect(0, 0, w, h);
- int64_t now = time(NULL);
- char *name = NULL;
- char *info = NULL;
- fz_display_list *dlist = NULL;
- fz_var(dlist);
- fz_var(info);
- fz_var(name);
- fz_try(ctx)
- {
- info = pdf_format_signature_info(ctx, signer, flags, reason, location, now, &name);
- if (graphic)
- dlist = pdf_signature_appearance_signed(ctx, rect, lang, graphic, NULL, info, logo);
- else if (flags & PDF_SIGNATURE_SHOW_GRAPHIC_NAME)
- dlist = pdf_signature_appearance_signed(ctx, rect, lang, NULL, name, info, logo);
- else
- dlist = pdf_signature_appearance_signed(ctx, rect, lang, NULL, NULL, info, logo);
- }
- fz_always(ctx)
- {
- fz_free(ctx, info);
- fz_free(ctx, name);
- }
- fz_catch(ctx)
- fz_rethrow(ctx);
- return dlist;
- }
- fz_pixmap *pdf_preview_signature_as_pixmap(fz_context *ctx,
- int w, int h, fz_text_language lang,
- pdf_pkcs7_signer *signer,
- int flags,
- fz_image *graphic,
- const char *reason,
- const char *location)
- {
- fz_pixmap *pix;
- fz_display_list *dlist = pdf_preview_signature_as_display_list(ctx,
- w, h, lang,
- signer, flags, graphic, reason, location);
- fz_try(ctx)
- pix = fz_new_pixmap_from_display_list(ctx, dlist, fz_identity, fz_device_rgb(ctx), 0);
- fz_always(ctx)
- fz_drop_display_list(ctx, dlist);
- fz_catch(ctx)
- fz_rethrow(ctx);
- return pix;
- }
- void pdf_clear_signature(fz_context *ctx, pdf_annot *widget)
- {
- int flags;
- fz_display_list *dlist = NULL;
- if (pdf_dict_get_inheritable(ctx, widget->obj, PDF_NAME(FT)) != PDF_NAME(Sig))
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
- if (pdf_widget_is_readonly(ctx, widget))
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "read only signature cannot be cleared");
- begin_widget_op(ctx, widget, "Clear Signature");
- fz_var(dlist);
- fz_try(ctx)
- {
- fz_text_language lang = pdf_annot_language(ctx, (pdf_annot *)widget);
- fz_rect rect = pdf_annot_rect(ctx, widget);
- pdf_begin_operation(ctx, widget->page->doc, "Clear Signature");
- if (pdf_widget_is_readonly(ctx, widget))
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "Signature read only, it cannot be cleared.");
- pdf_xref_remove_unsaved_signature(ctx, ((pdf_annot *)widget)->page->doc, ((pdf_annot *)widget)->obj);
- pdf_dirty_annot(ctx, widget);
- flags = pdf_dict_get_int(ctx, ((pdf_annot *)widget)->obj, PDF_NAME(F));
- flags &= ~PDF_ANNOT_IS_LOCKED;
- if (flags)
- pdf_dict_put_int(ctx, ((pdf_annot *)widget)->obj, PDF_NAME(F), flags);
- else
- pdf_dict_del(ctx, ((pdf_annot *)widget)->obj, PDF_NAME(F));
- pdf_dict_del(ctx, ((pdf_annot *)widget)->obj, PDF_NAME(V));
- dlist = pdf_signature_appearance_unsigned(ctx, rect, lang);
- pdf_set_annot_appearance_from_display_list(ctx, widget, "N", NULL, fz_identity, dlist);
- end_widget_op(ctx, widget);
- }
- fz_always(ctx)
- {
- fz_drop_display_list(ctx, dlist);
- }
- fz_catch(ctx)
- {
- abandon_widget_op(ctx, widget);
- fz_rethrow(ctx);
- }
- }
- 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_distinguished_name(fz_context *ctx, pdf_pkcs7_distinguished_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_distinguished_name(fz_context *ctx, pdf_pkcs7_distinguished_name *name)
- {
- const char *parts[] = {
- "cn=", "",
- ", o=", "",
- ", ou=", "",
- ", email=", "",
- ", c=", ""};
- size_t len = 1;
- char *s;
- int i;
- if (name == NULL)
- return NULL;
- parts[1] = name->cn;
- parts[3] = name->o;
- parts[5] = name->ou;
- parts[7] = name->email;
- parts[9] = name->c;
- 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_distinguished_name *pdf_signature_get_widget_signatory(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_annot *widget)
- {
- if (!widget->page)
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
- return pdf_signature_get_signatory(ctx, verifier, widget->page->doc, widget->obj);
- }
- pdf_pkcs7_distinguished_name *pdf_signature_get_signatory(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature)
- {
- char *contents = NULL;
- size_t contents_len;
- pdf_pkcs7_distinguished_name *dn;
- if (pdf_dict_get_inheritable(ctx, signature, PDF_NAME(FT)) != PDF_NAME(Sig))
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
- if (!pdf_signature_is_signed(ctx, doc, signature))
- return NULL;
- contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
- if (contents_len == 0)
- return NULL;
- 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_widget_digest(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_annot *widget)
- {
- if (!widget->page)
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
- return pdf_check_digest(ctx, verifier, widget->page->doc, widget->obj);
- }
- 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;
- size_t contents_len;
- if (pdf_dict_get_inheritable(ctx, signature, PDF_NAME(FT)) != PDF_NAME(Sig))
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
- if (!pdf_signature_is_signed(ctx, doc, signature))
- return PDF_SIGNATURE_ERROR_NOT_SIGNED;
- 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_widget_certificate(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_annot *w)
- {
- if (!w->page)
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
- return pdf_check_certificate(ctx, verifier, w->page->doc, w->obj);
- }
- 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_error result = PDF_SIGNATURE_ERROR_UNKNOWN;
- if (pdf_dict_get_inheritable(ctx, signature, PDF_NAME(FT)) != PDF_NAME(Sig))
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
- if (!pdf_signature_is_signed(ctx, doc, signature))
- return PDF_SIGNATURE_ERROR_NOT_SIGNED;
- contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
- 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;
- }
|