comparison mupdf-source/platform/java/jni/pkcs7signer.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2021 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
23 /* PKCS7Signer interface */
24
25 typedef struct
26 {
27 pdf_pkcs7_signer base; // Mupdf callbacks
28 int refs;
29 jobject java_signer;
30 } java_pkcs7_signer;
31
32 static pdf_pkcs7_signer *signer_keep(fz_context *ctx, pdf_pkcs7_signer *signer_)
33 {
34 java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
35
36 if (!signer) return NULL;
37
38 return fz_keep_imp(ctx, signer, &signer->refs);
39 }
40
41 static void signer_drop(fz_context *ctx, pdf_pkcs7_signer *signer_)
42 {
43 java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
44
45 if (!signer) return;
46
47 if (fz_drop_imp(ctx, signer, &signer->refs))
48 {
49 jboolean detach = JNI_FALSE;
50 JNIEnv *env = NULL;
51
52 env = jni_attach_thread(&detach);
53 if (env == NULL)
54 {
55 fz_warn(ctx, "cannot attach to JVM in signer_drop");
56 fz_free(ctx, signer);
57 jni_detach_thread(detach);
58 return;
59 }
60
61 (*env)->DeleteGlobalRef(env, signer->java_signer);
62 fz_free(ctx, signer);
63
64 jni_detach_thread(detach);
65 }
66 }
67
68 static char *string_field_to_utfchars(fz_context *ctx, JNIEnv *env, jobject obj, jfieldID fid)
69 {
70 const char *str = NULL;
71 char *val = NULL;
72 jobject jstr;
73
74 jstr = (*env)->GetObjectField(env, obj, fid);
75 if (!jstr) return NULL;
76
77 str = (*env)->GetStringUTFChars(env, jstr, NULL);
78 if (!str)
79 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot not get UTF string");
80
81 fz_try(ctx)
82 val = Memento_label(fz_strdup(ctx, str), "string field");
83 fz_always(ctx)
84 (*env)->ReleaseStringUTFChars(env, jstr, str);
85 fz_catch(ctx)
86 fz_rethrow(ctx);
87
88 return val;
89 }
90
91 static pdf_pkcs7_distinguished_name *signer_distinguished_name(fz_context *ctx, pdf_pkcs7_signer *signer_)
92 {
93 java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
94 pdf_pkcs7_distinguished_name *name = NULL;
95 jboolean detach = JNI_FALSE;
96 jobject desname = NULL;
97 JNIEnv *env = NULL;
98
99 if (signer == NULL) return NULL;
100
101 env = jni_attach_thread(&detach);
102 if (env == NULL)
103 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in pdf_pkcs7_distinguished_name");
104
105 desname = (*env)->CallObjectMethod(env, signer->java_signer, mid_PKCS7Signer_name);
106 if ((*env)->ExceptionCheck(env))
107 fz_throw_java_and_detach_thread(ctx, env, detach);
108 if (desname == NULL)
109 fz_throw_and_detach_thread(ctx, detach, FZ_ERROR_GENERIC, "cannot retrieve distinguished name");
110
111 fz_var(name);
112 fz_try(ctx)
113 {
114 name = Memento_label(fz_calloc(ctx, 1, sizeof(*name)), "distinguished name");
115 name->cn = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_cn);
116 name->o = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_o);
117 name->ou = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_ou);
118 name->email = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_email);
119 name->c = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_c);
120 }
121 fz_catch(ctx)
122 {
123 if (name) fz_free(ctx, name->c);
124 if (name) fz_free(ctx, name->email);
125 if (name) fz_free(ctx, name->ou);
126 if (name) fz_free(ctx, name->o);
127 if (name) fz_free(ctx, name->cn);
128 fz_free(ctx, name);
129 fz_rethrow_and_detach_thread(ctx, detach);
130 }
131
132 jni_detach_thread(detach);
133
134 return name;
135 }
136
137 static size_t signer_max_digest_size(fz_context *ctx, pdf_pkcs7_signer *signer_)
138 {
139 java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
140 jboolean detach = JNI_FALSE;
141 size_t max_digest = 0;
142 int len;
143
144 JNIEnv *env = jni_attach_thread(&detach);
145 if (env == NULL)
146 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in signer_max_digest_size");
147
148 /* get the size in bytes we should allow for the digest buffer */
149 len = (*env)->CallIntMethod(env, signer->java_signer, mid_PKCS7Signer_maxDigest);
150 if (len < 0)
151 len = 0;
152 max_digest = (size_t)len;
153 if ((*env)->ExceptionCheck(env))
154 fz_throw_java_and_detach_thread(ctx, env, detach);
155
156 jni_detach_thread(detach);
157
158 return max_digest;
159 }
160
161 static int signer_create_digest(fz_context *ctx, pdf_pkcs7_signer *signer_, fz_stream *stm, unsigned char *digest, size_t digest_len)
162 {
163 java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
164 jobject jsigner = signer->java_signer;
165 jboolean detach = JNI_FALSE;
166 jobject jdigest;
167 jobject jstm;
168 int result = 1;
169
170 JNIEnv *env = jni_attach_thread(&detach);
171 if (env == NULL)
172 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in signer_create_digest");
173
174 jstm = to_FitzInputStream(ctx, env, stm);
175
176 jdigest = (*env)->CallObjectMethod(env, jsigner, mid_PKCS7Signer_sign, jstm);
177 if ((*env)->ExceptionCheck(env))
178 fz_throw_java_and_detach_thread(ctx, env, detach);
179 if (!jdigest)
180 fz_throw(ctx, FZ_ERROR_GENERIC, "did not receive digest from signer");
181
182 if (digest != NULL)
183 {
184 jbyte *src = NULL;
185 int srclen = 0;
186
187 src = (*env)->GetByteArrayElements(env, jdigest, 0);
188 if (src == NULL)
189 fz_throw_and_detach_thread(ctx, detach, FZ_ERROR_GENERIC, "cannot get digest");
190
191 srclen = (*env)->GetArrayLength(env, jdigest);
192
193 if ((size_t)srclen > digest_len)
194 {
195 (*env)->ReleaseByteArrayElements(env, jdigest, src, JNI_ABORT);
196 fz_throw_and_detach_thread(ctx, detach, FZ_ERROR_GENERIC, "digest destination shorter than digest");
197 }
198
199 memcpy(digest, src, srclen);
200 result = srclen;
201
202 (*env)->ReleaseByteArrayElements(env, jdigest, src, JNI_ABORT);
203 }
204
205 jni_detach_thread(detach);
206
207 return result;
208 }
209
210 static pdf_pkcs7_signer *pdf_pkcs7_java_signer_create(JNIEnv *env, fz_context *ctx, jobject java_signer)
211 {
212 java_pkcs7_signer *signer = Memento_label(fz_calloc(ctx, 1, sizeof(*signer)), "java_pkcs7_signer");
213
214 if (signer == NULL) return NULL;
215
216 signer->base.keep = signer_keep;
217 signer->base.drop = signer_drop;
218 signer->base.get_signing_name = signer_distinguished_name;
219 signer->base.max_digest_size = signer_max_digest_size;
220 signer->base.create_digest = signer_create_digest;
221 signer->refs = 1;
222
223 signer->java_signer = (*env)->NewGlobalRef(env, java_signer);
224 if (signer->java_signer == NULL)
225 {
226 fz_free(ctx, signer);
227 return NULL;
228 }
229
230 return &signer->base;
231 }
232
233 JNIEXPORT jlong JNICALL
234 FUN(PKCS7Signer_newNative)(JNIEnv *env, jclass cls, jobject jsigner)
235 {
236 fz_context *ctx = get_context(env);
237 pdf_pkcs7_signer *signer = NULL;
238
239 if (!ctx) return 0;
240 if (!jsigner) jni_throw_arg(env, "signer must not be null");
241
242 jsigner = (*env)->NewGlobalRef(env, jsigner);
243 if (!jsigner) jni_throw_arg(env, "unable to get reference to signer");
244
245 fz_try(ctx)
246 signer = pdf_pkcs7_java_signer_create(env, ctx, jsigner);
247 fz_catch(ctx)
248 {
249 (*env)->DeleteGlobalRef(env, jsigner);
250 jni_rethrow(env, ctx);
251 }
252
253 return jlong_cast(signer);
254 }
255
256
257 JNIEXPORT void JNICALL
258 FUN(PKCS7Signer_finalize)(JNIEnv *env, jobject self)
259 {
260 fz_context *ctx = get_context(env);
261 pdf_pkcs7_signer *signer = from_PKCS7Signer_safe(env, self);
262 if (!ctx || !signer) return;
263 (*env)->SetLongField(env, self, fid_PKCS7Signer_pointer, 0);
264 pdf_drop_signer(ctx, signer);
265 }