1#include "mupdf/fitz.h"
2#include "mupdf/pdf.h"
3#include "../fitz/fitz-imp.h"
4
5#include <string.h>
6
7void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, int hexdigest_offset, int hexdigest_length, pdf_pkcs7_signer *signer)
8{
9 fz_stream *stm = NULL;
10 fz_stream *in = NULL;
11 fz_range *brange = NULL;
12 int brange_len = pdf_array_len(ctx, byte_range)/2;
13 unsigned char *digest = NULL;
14 int digest_len;
15
16 fz_var(stm);
17 fz_var(in);
18 fz_var(brange);
19
20 if (hexdigest_length < 4)
21 fz_throw(ctx, FZ_ERROR_GENERIC, "Bad parameters to pdf_write_digest");
22
23 fz_try(ctx)
24 {
25 int i, res;
26
27 brange = fz_calloc(ctx, brange_len, sizeof(*brange));
28 for (i = 0; i < brange_len; i++)
29 {
30 brange[i].offset = pdf_array_get_int(ctx, byte_range, 2*i);
31 brange[i].length = pdf_array_get_int(ctx, byte_range, 2*i+1);
32 }
33
34 stm = fz_stream_from_output(ctx, out);
35 in = fz_open_range_filter(ctx, stm, brange, brange_len);
36
37 digest_len = (hexdigest_length - 2) / 2;
38 digest = fz_malloc(ctx, digest_len);
39 res = signer->create_digest(signer, in, digest, &digest_len);
40 if (!res)
41 fz_throw(ctx, FZ_ERROR_GENERIC, "pdf_pkcs7_create_digest failed");
42
43 fz_drop_stream(ctx, in);
44 in = NULL;
45 fz_drop_stream(ctx, stm);
46 stm = NULL;
47
48 fz_seek_output(ctx, out, hexdigest_offset+1, SEEK_SET);
49
50 for (i = 0; i < digest_len; i++)
51 fz_write_printf(ctx, out, "%02x", digest[i]);
52 }
53 fz_always(ctx)
54 {
55 fz_free(ctx, digest);
56 fz_free(ctx, brange);
57 fz_drop_stream(ctx, stm);
58 fz_drop_stream(ctx, in);
59 }
60 fz_catch(ctx)
61 {
62 fz_rethrow(ctx);
63 }
64}
65
66void pdf_sign_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, pdf_pkcs7_signer *signer)
67{
68 pdf_pkcs7_designated_name *dn = NULL;
69 fz_buffer *fzbuf = NULL;
70
71 fz_try(ctx)
72 {
73 const char *dn_str;
74 pdf_obj *wobj = ((pdf_annot *)widget)->obj;
75 fz_rect rect;
76
77 rect = pdf_dict_get_rect(ctx, wobj, PDF_NAME(Rect));
78
79 /* Create an appearance stream only if the signature is intended to be visible */
80 if (!fz_is_empty_rect(rect))
81 {
82 dn = signer->designated_name(signer);
83 fzbuf = fz_new_buffer(ctx, 256);
84 if (!dn->cn)
85 fz_throw(ctx, FZ_ERROR_GENERIC, "Certificate has no common name");
86
87 fz_append_printf(ctx, fzbuf, "cn=%s", dn->cn);
88
89 if (dn->o)
90 fz_append_printf(ctx, fzbuf, ", o=%s", dn->o);
91
92 if (dn->ou)
93 fz_append_printf(ctx, fzbuf, ", ou=%s", dn->ou);
94
95 if (dn->email)
96 fz_append_printf(ctx, fzbuf, ", email=%s", dn->email);
97
98 if (dn->c)
99 fz_append_printf(ctx, fzbuf, ", c=%s", dn->c);
100
101 dn_str = fz_string_from_buffer(ctx, fzbuf);
102 pdf_update_signature_appearance(ctx, (pdf_annot *)widget, dn->cn, dn_str, NULL);
103 }
104
105 pdf_signature_set_value(ctx, doc, wobj, signer);
106 }
107 fz_always(ctx)
108 {
109 signer->drop_designated_name(signer, dn);
110 fz_drop_buffer(ctx, fzbuf);
111 }
112 fz_catch(ctx)
113 {
114 fz_rethrow(ctx);
115 }
116}
117
118void pdf_clear_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget)
119{
120 int flags;
121
122 flags = pdf_dict_get_int(ctx, ((pdf_annot *) widget)->obj, PDF_NAME(F));
123 flags &= ~PDF_ANNOT_IS_LOCKED;
124 if (flags)
125 pdf_dict_put_int(ctx, ((pdf_annot *) widget)->obj, PDF_NAME(F), flags);
126 else
127 pdf_dict_del(ctx, ((pdf_annot *) widget)->obj, PDF_NAME(F));
128
129 pdf_dict_del(ctx, ((pdf_annot *) widget)->obj, PDF_NAME(V));
130
131 pdf_update_signature_appearance(ctx, widget, NULL, NULL, NULL);
132}
133