1 | #include "mupdf/fitz.h" |
2 | #include "mupdf/pdf.h" |
3 | #include "../fitz/fitz-imp.h" |
4 | |
5 | #include <string.h> |
6 | |
7 | void 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 | |
66 | void 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 | |
118 | void 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 | |