1#include "mupdf/fitz.h"
2#include "mupdf/pdf.h"
3
4#include "mupdf/helpers/pkcs7-check.h"
5
6char *pdf_signature_error_description(enum pdf_signature_error err)
7{
8 switch (err)
9 {
10 case PDF_SIGNATURE_ERROR_OKAY:
11 return "";
12 case PDF_SIGNATURE_ERROR_NO_SIGNATURES:
13 return "No signatures.";
14 case PDF_SIGNATURE_ERROR_NO_CERTIFICATE:
15 return "No certificate.";
16 case PDF_SIGNATURE_ERROR_DIGEST_FAILURE:
17 return "Signature invalidated by change to document.";
18 case PDF_SIGNATURE_ERROR_SELF_SIGNED:
19 return "Self-signed certificate.";
20 case PDF_SIGNATURE_ERROR_SELF_SIGNED_IN_CHAIN:
21 return "Self-signed certificate in chain.";
22 case PDF_SIGNATURE_ERROR_NOT_TRUSTED:
23 return "Certificate not trusted.";
24 default:
25 case PDF_SIGNATURE_ERROR_UNKNOWN:
26 return "Unknown error.";
27 }
28}
29
30#ifdef HAVE_LIBCRYPTO
31#include "mupdf/helpers/pkcs7-openssl.h"
32#include <string.h>
33
34static void pdf_format_designated_name(pdf_pkcs7_designated_name *name, char *buf, int buflen)
35{
36 int i, n;
37 const char *part[] = {
38 "CN=", name->cn,
39 ", O=", name->o,
40 ", OU=", name->ou,
41 ", emailAddress=", name->email,
42 ", C=", name->c};
43
44 if (buflen)
45 buf[0] = 0;
46
47 n = sizeof(part)/sizeof(*part);
48 for (i = 0; i < n; i++)
49 if (part[i])
50 fz_strlcat(buf, part[i], buflen);
51}
52
53void pdf_signature_designated_name(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char *buf, int buflen)
54{
55 char *contents = NULL;
56 int contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
57 pdf_pkcs7_designated_name *name = NULL;
58 fz_try(ctx)
59 {
60 name = pkcs7_openssl_designated_name(ctx, contents, contents_len);
61 if (name)
62 {
63 pdf_format_designated_name(name, buf, buflen);
64 pkcs7_openssl_drop_designated_name(ctx, name);
65 }
66 else if (buflen > 0)
67 buf[0] = '\0';
68 }
69 fz_always(ctx)
70 fz_free(ctx, contents);
71 fz_catch(ctx)
72 fz_rethrow(ctx);
73}
74
75enum pdf_signature_error pdf_check_digest(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
76{
77 enum pdf_signature_error err;
78 fz_stream *bytes = NULL;
79 char *contents = NULL;
80 int contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
81 fz_var(err);
82 fz_var(bytes);
83 fz_try(ctx)
84 {
85 bytes = pdf_signature_hash_bytes(ctx, doc, signature);
86 err = pkcs7_openssl_check_digest(ctx, bytes, contents, contents_len);
87 }
88 fz_always(ctx)
89 {
90 fz_drop_stream(ctx, bytes);
91 fz_free(ctx, contents);
92 }
93 fz_catch(ctx)
94 {
95 fz_rethrow(ctx);
96 }
97
98 return err;
99}
100
101enum pdf_signature_error pdf_check_certificate(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
102{
103 char *contents = NULL;
104 int contents_len = pdf_signature_contents(ctx, doc, signature, &contents);
105 enum pdf_signature_error result;
106 fz_try(ctx)
107 result = pkcs7_openssl_check_certificate(contents, contents_len);
108 fz_always(ctx)
109 fz_free(ctx, contents);
110 fz_catch(ctx)
111 fz_rethrow(ctx);
112 return result;
113}
114
115int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char *ebuf, int ebufsize)
116{
117 int res = 0;
118
119 if (pdf_xref_obj_is_unsaved_signature(doc, signature))
120 {
121 fz_strlcpy(ebuf, "Signed but document yet to be saved.", ebufsize);
122 if (ebufsize > 0)
123 ebuf[ebufsize-1] = 0;
124 return 0;
125 }
126
127 fz_var(res);
128 fz_try(ctx)
129 {
130 if (pdf_signature_is_signed(ctx, doc, signature))
131 {
132 enum pdf_signature_error err;
133
134 err = pdf_check_digest(ctx, doc, signature);
135 if (err == PDF_SIGNATURE_ERROR_OKAY)
136 err = pdf_check_certificate(ctx, doc, signature);
137
138 fz_strlcpy(ebuf, pdf_signature_error_description(err), ebufsize);
139 res = (err == PDF_SIGNATURE_ERROR_OKAY);
140
141 switch (err)
142 {
143 case PDF_SIGNATURE_ERROR_SELF_SIGNED:
144 case PDF_SIGNATURE_ERROR_SELF_SIGNED_IN_CHAIN:
145 case PDF_SIGNATURE_ERROR_NOT_TRUSTED:
146 {
147 int len;
148 fz_strlcat(ebuf, " (", ebufsize);
149 len = strlen(ebuf);
150 pdf_signature_designated_name(ctx, doc, signature, ebuf + len, ebufsize - len);
151 fz_strlcat(ebuf, ")", ebufsize);
152 }
153 break;
154 default:
155 break;
156 }
157 }
158 else
159 {
160 res = 0;
161 fz_strlcpy(ebuf, "Not signed.", ebufsize);
162 }
163 }
164 fz_catch(ctx)
165 {
166 res = 0;
167 fz_strlcpy(ebuf, fz_caught_message(ctx), ebufsize);
168 }
169
170 if (ebufsize > 0)
171 ebuf[ebufsize-1] = 0;
172
173 return res;
174}
175
176#else
177
178void pdf_signature_designated_name(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char *buf, int buflen)
179{
180 fz_throw(ctx, FZ_ERROR_GENERIC, "No OpenSSL support.");
181}
182
183enum pdf_signature_error pdf_check_digest(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
184{
185 fz_throw(ctx, FZ_ERROR_GENERIC, "No OpenSSL support.");
186 return 0;
187}
188
189enum pdf_signature_error pdf_check_certificate(fz_context *ctx, pdf_document *doc, pdf_obj *signature)
190{
191 fz_throw(ctx, FZ_ERROR_GENERIC, "No OpenSSL support.");
192 return 0;
193}
194
195
196int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_obj *signature, char *ebuf, int ebufsize)
197{
198 fz_strlcpy(ebuf, "No digital signing support in this build", ebufsize);
199 return 0;
200}
201
202#endif
203