pdf-signature.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. // Copyright (C) 2004-2025 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/fitz.h"
  23. #include "pdf-annot-imp.h"
  24. #include <string.h>
  25. #include <time.h>
  26. enum
  27. {
  28. PDF_SIGFLAGS_SIGSEXIST = 1,
  29. PDF_SIGFLAGS_APPENDONLY = 2
  30. };
  31. static void
  32. begin_widget_op(fz_context *ctx, pdf_annot *annot, const char *op)
  33. {
  34. if (!annot->page)
  35. fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
  36. pdf_begin_operation(ctx, annot->page->doc, op);
  37. }
  38. static void
  39. end_widget_op(fz_context *ctx, pdf_annot *annot)
  40. {
  41. pdf_end_operation(ctx, annot->page->doc);
  42. }
  43. static void
  44. abandon_widget_op(fz_context *ctx, pdf_annot *annot)
  45. {
  46. pdf_abandon_operation(ctx, annot->page->doc);
  47. }
  48. 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)
  49. {
  50. fz_stream *stm = NULL;
  51. fz_stream *in = NULL;
  52. fz_range *brange = NULL;
  53. int brange_len = pdf_array_len(ctx, byte_range)/2;
  54. unsigned char *digest = NULL;
  55. size_t digest_len;
  56. pdf_obj *v = pdf_dict_get(ctx, field, PDF_NAME(V));
  57. size_t len;
  58. char *cstr = NULL;
  59. fz_var(stm);
  60. fz_var(in);
  61. fz_var(brange);
  62. fz_var(digest);
  63. fz_var(cstr);
  64. if (hexdigest_length < 4)
  65. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Bad parameters to pdf_write_digest");
  66. len = (hexdigest_length - 2) / 2;
  67. fz_try(ctx)
  68. {
  69. int i;
  70. size_t z;
  71. brange = fz_calloc(ctx, brange_len, sizeof(*brange));
  72. for (i = 0; i < brange_len; i++)
  73. {
  74. brange[i].offset = pdf_array_get_int(ctx, byte_range, 2*i);
  75. brange[i].length = pdf_array_get_int(ctx, byte_range, 2*i+1);
  76. }
  77. stm = fz_stream_from_output(ctx, out);
  78. in = fz_open_range_filter(ctx, stm, brange, brange_len);
  79. digest = fz_malloc(ctx, len);
  80. digest_len = signer->create_digest(ctx, signer, in, digest, len);
  81. if (digest_len == 0)
  82. fz_throw(ctx, FZ_ERROR_ARGUMENT, "signer provided no signature digest");
  83. if (digest_len > len)
  84. fz_throw(ctx, FZ_ERROR_ARGUMENT, "signature digest larger than space for digest");
  85. fz_drop_stream(ctx, in);
  86. in = NULL;
  87. fz_drop_stream(ctx, stm);
  88. stm = NULL;
  89. fz_seek_output(ctx, out, (int64_t)hexdigest_offset+1, SEEK_SET);
  90. cstr = fz_malloc(ctx, len);
  91. for (z = 0; z < len; z++)
  92. {
  93. int val = z < digest_len ? digest[z] : 0;
  94. fz_write_printf(ctx, out, "%02x", val);
  95. cstr[z] = val;
  96. }
  97. pdf_dict_put_string(ctx, v, PDF_NAME(Contents), cstr, len);
  98. }
  99. fz_always(ctx)
  100. {
  101. fz_free(ctx, cstr);
  102. fz_free(ctx, digest);
  103. fz_free(ctx, brange);
  104. fz_drop_stream(ctx, stm);
  105. fz_drop_stream(ctx, in);
  106. }
  107. fz_catch(ctx)
  108. {
  109. fz_rethrow(ctx);
  110. }
  111. }
  112. typedef struct fieldname_prefix
  113. {
  114. struct fieldname_prefix *prev;
  115. char name[FZ_FLEXIBLE_ARRAY];
  116. } fieldname_prefix;
  117. typedef struct
  118. {
  119. pdf_locked_fields *locked;
  120. fieldname_prefix *prefix;
  121. } sig_locking_data;
  122. static void
  123. check_field_locking(fz_context *ctx, pdf_obj *obj, void *data_, pdf_obj **ff)
  124. {
  125. fieldname_prefix *prefix = NULL;
  126. sig_locking_data *data = (sig_locking_data *)data_;
  127. fz_var(prefix);
  128. fz_try(ctx)
  129. {
  130. const char *name = NULL;
  131. size_t n = 1;
  132. pdf_obj *t;
  133. t = pdf_dict_get(ctx, obj, PDF_NAME(T));
  134. if (t != NULL)
  135. {
  136. name = pdf_to_text_string(ctx, t);
  137. n += strlen(name);
  138. }
  139. if (data->prefix->name[0] && name)
  140. n += 1;
  141. if (data->prefix->name[0])
  142. n += strlen(data->prefix->name);
  143. prefix = fz_malloc_flexible(ctx, fieldname_prefix, name, n);
  144. prefix->prev = data->prefix;
  145. if (data->prefix->name[0])
  146. strcpy(prefix->name, data->prefix->name);
  147. if (data->prefix->name[0] && name)
  148. strcat(prefix->name, ".");
  149. if (name)
  150. strcat(prefix->name, name);
  151. data->prefix = prefix;
  152. if (pdf_name_eq(ctx, pdf_dict_get(ctx, obj, PDF_NAME(Type)), PDF_NAME(Annot)) &&
  153. pdf_name_eq(ctx, pdf_dict_get(ctx, obj, PDF_NAME(Subtype)), PDF_NAME(Widget)))
  154. {
  155. int flags = pdf_to_int(ctx, *ff);
  156. if (((flags & PDF_FIELD_IS_READ_ONLY) == 0) && /* Field is not currently locked */
  157. pdf_is_field_locked(ctx, data->locked, data->prefix->name)) /* Field should be locked */
  158. pdf_dict_put_int(ctx, obj, PDF_NAME(Ff), flags | PDF_FIELD_IS_READ_ONLY);
  159. }
  160. }
  161. fz_catch(ctx)
  162. {
  163. if (prefix)
  164. {
  165. data->prefix = prefix->prev;
  166. fz_free(ctx, prefix);
  167. }
  168. fz_rethrow(ctx);
  169. }
  170. }
  171. static void
  172. pop_field_locking(fz_context *ctx, pdf_obj *obj, void *data_)
  173. {
  174. fieldname_prefix *prefix;
  175. sig_locking_data *data = (sig_locking_data *)data_;
  176. prefix = data->prefix;
  177. data->prefix = data->prefix->prev;
  178. fz_free(ctx, prefix);
  179. }
  180. static void enact_sig_locking(fz_context *ctx, pdf_document *doc, pdf_obj *sig)
  181. {
  182. pdf_locked_fields *locked = pdf_find_locked_fields_for_sig(ctx, doc, sig);
  183. pdf_obj *fields;
  184. static pdf_obj *ff_names[2] = { PDF_NAME(Ff), NULL };
  185. pdf_obj *ff = NULL;
  186. static fieldname_prefix null_prefix = { NULL, { 0 } };
  187. sig_locking_data data = { locked, &null_prefix };
  188. if (locked == NULL)
  189. return;
  190. fz_try(ctx)
  191. {
  192. fields = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/AcroForm/Fields");
  193. pdf_walk_tree(ctx, fields, PDF_NAME(Kids), check_field_locking, pop_field_locking, &data, &ff_names[0], &ff);
  194. }
  195. fz_always(ctx)
  196. pdf_drop_locked_fields(ctx, locked);
  197. fz_catch(ctx)
  198. {
  199. pop_field_locking(ctx, NULL, &data);
  200. fz_rethrow(ctx);
  201. }
  202. }
  203. void
  204. pdf_sign_signature_with_appearance(fz_context *ctx, pdf_annot *widget, pdf_pkcs7_signer *signer, int64_t t, fz_display_list *disp_list)
  205. {
  206. pdf_document *doc;
  207. if (pdf_dict_get_inheritable(ctx, widget->obj, PDF_NAME(FT)) != PDF_NAME(Sig))
  208. fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
  209. if (pdf_widget_is_readonly(ctx, widget))
  210. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Signature is read only, it cannot be signed.");
  211. begin_widget_op(ctx, widget, "Sign signature");
  212. doc = widget->page->doc;
  213. fz_try(ctx)
  214. {
  215. pdf_obj *wobj = ((pdf_annot *)widget)->obj;
  216. pdf_obj *form;
  217. int sf;
  218. pdf_dirty_annot(ctx, widget);
  219. /* Ensure that all fields that will be locked by this signature
  220. * are marked as ReadOnly. */
  221. enact_sig_locking(ctx, doc, wobj);
  222. if (disp_list)
  223. pdf_set_annot_appearance_from_display_list(ctx, widget, "N", NULL, fz_identity, disp_list);
  224. /* Update the SigFlags for the document if required */
  225. form = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/AcroForm");
  226. if (!form)
  227. {
  228. pdf_obj *root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME(Root));
  229. form = pdf_dict_put_dict(ctx, root, PDF_NAME(AcroForm), 1);
  230. }
  231. sf = pdf_to_int(ctx, pdf_dict_get(ctx, form, PDF_NAME(SigFlags)));
  232. if ((sf & (PDF_SIGFLAGS_SIGSEXIST | PDF_SIGFLAGS_APPENDONLY)) != (PDF_SIGFLAGS_SIGSEXIST | PDF_SIGFLAGS_APPENDONLY))
  233. pdf_dict_put_int(ctx, form, PDF_NAME(SigFlags), sf | PDF_SIGFLAGS_SIGSEXIST | PDF_SIGFLAGS_APPENDONLY);
  234. pdf_signature_set_value(ctx, doc, wobj, signer, t);
  235. end_widget_op(ctx, widget);
  236. }
  237. fz_catch(ctx)
  238. {
  239. abandon_widget_op(ctx, widget);
  240. fz_rethrow(ctx);
  241. }
  242. }
  243. static pdf_pkcs7_distinguished_name placeholder_dn = {
  244. "Your Common Name Here",
  245. "Organization",
  246. "Organizational Unit",
  247. "Email",
  248. "Country"
  249. };
  250. static char *
  251. pdf_format_signature_info(fz_context *ctx, pdf_pkcs7_signer *signer, int flags, const char *reason, const char *location, int64_t now, char **name)
  252. {
  253. pdf_pkcs7_distinguished_name *dn = NULL;
  254. char *info;
  255. fz_var(dn);
  256. fz_try(ctx)
  257. {
  258. if (signer)
  259. dn = signer->get_signing_name(ctx, signer);
  260. if (!dn)
  261. dn = &placeholder_dn;
  262. *name = fz_strdup(ctx, dn->cn ? dn->cn : "Your Common Name Here");
  263. info = pdf_signature_info(ctx,
  264. (flags & PDF_SIGNATURE_SHOW_TEXT_NAME) ? *name : NULL,
  265. (flags & PDF_SIGNATURE_SHOW_DN) ? dn : NULL,
  266. reason,
  267. location,
  268. (flags & PDF_SIGNATURE_SHOW_DATE) ? now : -1,
  269. (flags & PDF_SIGNATURE_SHOW_LABELS) ? 1 : 0);
  270. }
  271. fz_always(ctx)
  272. {
  273. if (dn != &placeholder_dn)
  274. pdf_signature_drop_distinguished_name(ctx, dn);
  275. }
  276. fz_catch(ctx)
  277. fz_rethrow(ctx);
  278. return info;
  279. }
  280. void pdf_sign_signature(fz_context *ctx, pdf_annot *widget,
  281. pdf_pkcs7_signer *signer,
  282. int flags,
  283. fz_image *graphic,
  284. const char *reason,
  285. const char *location)
  286. {
  287. int logo = flags & PDF_SIGNATURE_SHOW_LOGO;
  288. fz_rect rect = pdf_annot_rect(ctx, widget);
  289. fz_text_language lang = pdf_annot_language(ctx, widget);
  290. #ifdef CLUSTER
  291. int64_t now = 1112281971; /* release date of MuPDF 0.1 */
  292. #else
  293. int64_t now = time(NULL);
  294. #endif
  295. char *name = NULL;
  296. char *info = NULL;
  297. fz_display_list *dlist = NULL;
  298. fz_var(dlist);
  299. fz_var(info);
  300. fz_var(name);
  301. /* Create an appearance stream only if the signature is intended to be visible */
  302. fz_try(ctx)
  303. {
  304. if (!fz_is_empty_rect(rect))
  305. {
  306. info = pdf_format_signature_info(ctx, signer, flags, reason, location, now, &name);
  307. if (graphic)
  308. dlist = pdf_signature_appearance_signed(ctx, rect, lang, graphic, NULL, info, logo);
  309. else if (flags & PDF_SIGNATURE_SHOW_GRAPHIC_NAME)
  310. dlist = pdf_signature_appearance_signed(ctx, rect, lang, NULL, name, info, logo);
  311. else
  312. dlist = pdf_signature_appearance_signed(ctx, rect, lang, NULL, NULL, info, logo);
  313. }
  314. pdf_sign_signature_with_appearance(ctx, widget, signer, now, dlist);
  315. }
  316. fz_always(ctx)
  317. {
  318. fz_free(ctx, info);
  319. fz_free(ctx, name);
  320. fz_drop_display_list(ctx, dlist);
  321. }
  322. fz_catch(ctx)
  323. fz_rethrow(ctx);
  324. }
  325. fz_display_list *pdf_preview_signature_as_display_list(fz_context *ctx,
  326. float w, float h, fz_text_language lang,
  327. pdf_pkcs7_signer *signer,
  328. int flags,
  329. fz_image *graphic,
  330. const char *reason,
  331. const char *location)
  332. {
  333. int logo = flags & PDF_SIGNATURE_SHOW_LOGO;
  334. fz_rect rect = fz_make_rect(0, 0, w, h);
  335. int64_t now = time(NULL);
  336. char *name = NULL;
  337. char *info = NULL;
  338. fz_display_list *dlist = NULL;
  339. fz_var(dlist);
  340. fz_var(info);
  341. fz_var(name);
  342. fz_try(ctx)
  343. {
  344. info = pdf_format_signature_info(ctx, signer, flags, reason, location, now, &name);
  345. if (graphic)
  346. dlist = pdf_signature_appearance_signed(ctx, rect, lang, graphic, NULL, info, logo);
  347. else if (flags & PDF_SIGNATURE_SHOW_GRAPHIC_NAME)
  348. dlist = pdf_signature_appearance_signed(ctx, rect, lang, NULL, name, info, logo);
  349. else
  350. dlist = pdf_signature_appearance_signed(ctx, rect, lang, NULL, NULL, info, logo);
  351. }
  352. fz_always(ctx)
  353. {
  354. fz_free(ctx, info);
  355. fz_free(ctx, name);
  356. }
  357. fz_catch(ctx)
  358. fz_rethrow(ctx);
  359. return dlist;
  360. }
  361. fz_pixmap *pdf_preview_signature_as_pixmap(fz_context *ctx,
  362. int w, int h, fz_text_language lang,
  363. pdf_pkcs7_signer *signer,
  364. int flags,
  365. fz_image *graphic,
  366. const char *reason,
  367. const char *location)
  368. {
  369. fz_pixmap *pix;
  370. fz_display_list *dlist = pdf_preview_signature_as_display_list(ctx,
  371. w, h, lang,
  372. signer, flags, graphic, reason, location);
  373. fz_try(ctx)
  374. pix = fz_new_pixmap_from_display_list(ctx, dlist, fz_identity, fz_device_rgb(ctx), 0);
  375. fz_always(ctx)
  376. fz_drop_display_list(ctx, dlist);
  377. fz_catch(ctx)
  378. fz_rethrow(ctx);
  379. return pix;
  380. }
  381. void pdf_clear_signature(fz_context *ctx, pdf_annot *widget)
  382. {
  383. int flags;
  384. fz_display_list *dlist = NULL;
  385. if (pdf_dict_get_inheritable(ctx, widget->obj, PDF_NAME(FT)) != PDF_NAME(Sig))
  386. fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
  387. if (pdf_widget_is_readonly(ctx, widget))
  388. fz_throw(ctx, FZ_ERROR_ARGUMENT, "read only signature cannot be cleared");
  389. begin_widget_op(ctx, widget, "Clear Signature");
  390. fz_var(dlist);
  391. fz_try(ctx)
  392. {
  393. fz_text_language lang = pdf_annot_language(ctx, (pdf_annot *)widget);
  394. fz_rect rect = pdf_annot_rect(ctx, widget);
  395. pdf_begin_operation(ctx, widget->page->doc, "Clear Signature");
  396. if (pdf_widget_is_readonly(ctx, widget))
  397. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Signature read only, it cannot be cleared.");
  398. pdf_xref_remove_unsaved_signature(ctx, ((pdf_annot *)widget)->page->doc, ((pdf_annot *)widget)->obj);
  399. pdf_dirty_annot(ctx, widget);
  400. flags = pdf_dict_get_int(ctx, ((pdf_annot *)widget)->obj, PDF_NAME(F));
  401. flags &= ~PDF_ANNOT_IS_LOCKED;
  402. if (flags)
  403. pdf_dict_put_int(ctx, ((pdf_annot *)widget)->obj, PDF_NAME(F), flags);
  404. else
  405. pdf_dict_del(ctx, ((pdf_annot *)widget)->obj, PDF_NAME(F));
  406. pdf_dict_del(ctx, ((pdf_annot *)widget)->obj, PDF_NAME(V));
  407. dlist = pdf_signature_appearance_unsigned(ctx, rect, lang);
  408. pdf_set_annot_appearance_from_display_list(ctx, widget, "N", NULL, fz_identity, dlist);
  409. end_widget_op(ctx, widget);
  410. }
  411. fz_always(ctx)
  412. {
  413. fz_drop_display_list(ctx, dlist);
  414. }
  415. fz_catch(ctx)
  416. {
  417. abandon_widget_op(ctx, widget);
  418. fz_rethrow(ctx);
  419. }
  420. }
  421. void pdf_drop_signer(fz_context *ctx, pdf_pkcs7_signer *signer)
  422. {
  423. if (signer)
  424. signer->drop(ctx, signer);
  425. }
  426. void pdf_drop_verifier(fz_context *ctx, pdf_pkcs7_verifier *verifier)
  427. {
  428. if (verifier)
  429. verifier->drop(ctx, verifier);
  430. }
  431. char *pdf_signature_error_description(pdf_signature_error err)
  432. {
  433. switch (err)
  434. {
  435. case PDF_SIGNATURE_ERROR_OKAY:
  436. return "OK";
  437. case PDF_SIGNATURE_ERROR_NO_SIGNATURES:
  438. return "No signatures.";
  439. case PDF_SIGNATURE_ERROR_NO_CERTIFICATE:
  440. return "No certificate.";
  441. case PDF_SIGNATURE_ERROR_DIGEST_FAILURE:
  442. return "Signature invalidated by change to document.";
  443. case PDF_SIGNATURE_ERROR_SELF_SIGNED:
  444. return "Self-signed certificate.";
  445. case PDF_SIGNATURE_ERROR_SELF_SIGNED_IN_CHAIN:
  446. return "Self-signed certificate in chain.";
  447. case PDF_SIGNATURE_ERROR_NOT_TRUSTED:
  448. return "Certificate not trusted.";
  449. default:
  450. case PDF_SIGNATURE_ERROR_UNKNOWN:
  451. return "Unknown error.";
  452. }
  453. }
  454. void pdf_signature_drop_distinguished_name(fz_context *ctx, pdf_pkcs7_distinguished_name *dn)
  455. {
  456. if (dn)
  457. {
  458. fz_free(ctx, dn->c);
  459. fz_free(ctx, dn->email);
  460. fz_free(ctx, dn->ou);
  461. fz_free(ctx, dn->o);
  462. fz_free(ctx, dn->cn);
  463. fz_free(ctx, dn);
  464. }
  465. }
  466. char *pdf_signature_format_distinguished_name(fz_context *ctx, pdf_pkcs7_distinguished_name *name)
  467. {
  468. const char *parts[] = {
  469. "cn=", "",
  470. ", o=", "",
  471. ", ou=", "",
  472. ", email=", "",
  473. ", c=", ""};
  474. size_t len = 1;
  475. char *s;
  476. int i;
  477. if (name == NULL)
  478. return NULL;
  479. parts[1] = name->cn;
  480. parts[3] = name->o;
  481. parts[5] = name->ou;
  482. parts[7] = name->email;
  483. parts[9] = name->c;
  484. for (i = 0; i < (int)nelem(parts); i++)
  485. if (parts[i])
  486. len += strlen(parts[i]);
  487. s = fz_malloc(ctx, len);
  488. s[0] = '\0';
  489. for (i = 0; i < (int)nelem(parts); i++)
  490. if (parts[i])
  491. fz_strlcat(s, parts[i], len);
  492. return s;
  493. }
  494. pdf_pkcs7_distinguished_name *pdf_signature_get_widget_signatory(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_annot *widget)
  495. {
  496. if (!widget->page)
  497. fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
  498. return pdf_signature_get_signatory(ctx, verifier, widget->page->doc, widget->obj);
  499. }
  500. pdf_pkcs7_distinguished_name *pdf_signature_get_signatory(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature)
  501. {
  502. char *contents = NULL;
  503. size_t contents_len;
  504. pdf_pkcs7_distinguished_name *dn;
  505. if (pdf_dict_get_inheritable(ctx, signature, PDF_NAME(FT)) != PDF_NAME(Sig))
  506. fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
  507. if (!pdf_signature_is_signed(ctx, doc, signature))
  508. return NULL;
  509. contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
  510. if (contents_len == 0)
  511. return NULL;
  512. fz_try(ctx)
  513. dn = verifier->get_signatory(ctx, verifier, (unsigned char *)contents, contents_len);
  514. fz_always(ctx)
  515. fz_free(ctx, contents);
  516. fz_catch(ctx)
  517. fz_rethrow(ctx);
  518. return dn;
  519. }
  520. pdf_signature_error pdf_check_widget_digest(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_annot *widget)
  521. {
  522. if (!widget->page)
  523. fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
  524. return pdf_check_digest(ctx, verifier, widget->page->doc, widget->obj);
  525. }
  526. pdf_signature_error pdf_check_digest(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature)
  527. {
  528. pdf_signature_error result = PDF_SIGNATURE_ERROR_UNKNOWN;
  529. fz_stream *bytes = NULL;
  530. char *contents = NULL;
  531. size_t contents_len;
  532. if (pdf_dict_get_inheritable(ctx, signature, PDF_NAME(FT)) != PDF_NAME(Sig))
  533. fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
  534. if (!pdf_signature_is_signed(ctx, doc, signature))
  535. return PDF_SIGNATURE_ERROR_NOT_SIGNED;
  536. contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
  537. fz_var(bytes);
  538. fz_try(ctx)
  539. {
  540. bytes = pdf_signature_hash_bytes(ctx, doc, signature);
  541. result = verifier->check_digest(ctx, verifier, bytes, (unsigned char *)contents, contents_len);
  542. }
  543. fz_always(ctx)
  544. {
  545. fz_drop_stream(ctx, bytes);
  546. fz_free(ctx, contents);
  547. }
  548. fz_catch(ctx)
  549. {
  550. fz_rethrow(ctx);
  551. }
  552. return result;
  553. }
  554. pdf_signature_error pdf_check_widget_certificate(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_annot *w)
  555. {
  556. if (!w->page)
  557. fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
  558. return pdf_check_certificate(ctx, verifier, w->page->doc, w->obj);
  559. }
  560. pdf_signature_error pdf_check_certificate(fz_context *ctx, pdf_pkcs7_verifier *verifier, pdf_document *doc, pdf_obj *signature)
  561. {
  562. char *contents = NULL;
  563. size_t contents_len;
  564. pdf_signature_error result = PDF_SIGNATURE_ERROR_UNKNOWN;
  565. if (pdf_dict_get_inheritable(ctx, signature, PDF_NAME(FT)) != PDF_NAME(Sig))
  566. fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation is not a signature widget");
  567. if (!pdf_signature_is_signed(ctx, doc, signature))
  568. return PDF_SIGNATURE_ERROR_NOT_SIGNED;
  569. contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
  570. fz_try(ctx)
  571. result = verifier->check_certificate(ctx, verifier, (unsigned char *)contents, contents_len);
  572. fz_always(ctx)
  573. fz_free(ctx, contents);
  574. fz_catch(ctx)
  575. fz_rethrow(ctx);
  576. return result;
  577. }