pkcs7signer.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. /* PKCS7Signer interface */
  23. typedef struct
  24. {
  25. pdf_pkcs7_signer base; // Mupdf callbacks
  26. int refs;
  27. jobject java_signer;
  28. } java_pkcs7_signer;
  29. static pdf_pkcs7_signer *signer_keep(fz_context *ctx, pdf_pkcs7_signer *signer_)
  30. {
  31. java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
  32. if (!signer) return NULL;
  33. return fz_keep_imp(ctx, signer, &signer->refs);
  34. }
  35. static void signer_drop(fz_context *ctx, pdf_pkcs7_signer *signer_)
  36. {
  37. java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
  38. if (!signer) return;
  39. if (fz_drop_imp(ctx, signer, &signer->refs))
  40. {
  41. jboolean detach = JNI_FALSE;
  42. JNIEnv *env = NULL;
  43. env = jni_attach_thread(&detach);
  44. if (env == NULL)
  45. {
  46. fz_warn(ctx, "cannot attach to JVM in signer_drop");
  47. fz_free(ctx, signer);
  48. jni_detach_thread(detach);
  49. return;
  50. }
  51. (*env)->DeleteGlobalRef(env, signer->java_signer);
  52. fz_free(ctx, signer);
  53. jni_detach_thread(detach);
  54. }
  55. }
  56. static char *string_field_to_utfchars(fz_context *ctx, JNIEnv *env, jobject obj, jfieldID fid)
  57. {
  58. const char *str = NULL;
  59. char *val = NULL;
  60. jobject jstr;
  61. jstr = (*env)->GetObjectField(env, obj, fid);
  62. if (!jstr) return NULL;
  63. str = (*env)->GetStringUTFChars(env, jstr, NULL);
  64. if (!str)
  65. fz_throw(ctx, FZ_ERROR_GENERIC, "cannot not get UTF string");
  66. fz_try(ctx)
  67. val = Memento_label(fz_strdup(ctx, str), "string field");
  68. fz_always(ctx)
  69. (*env)->ReleaseStringUTFChars(env, jstr, str);
  70. fz_catch(ctx)
  71. fz_rethrow(ctx);
  72. return val;
  73. }
  74. static pdf_pkcs7_distinguished_name *signer_distinguished_name(fz_context *ctx, pdf_pkcs7_signer *signer_)
  75. {
  76. java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
  77. pdf_pkcs7_distinguished_name *name = NULL;
  78. jboolean detach = JNI_FALSE;
  79. jobject desname = NULL;
  80. JNIEnv *env = NULL;
  81. if (signer == NULL) return NULL;
  82. env = jni_attach_thread(&detach);
  83. if (env == NULL)
  84. fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in pdf_pkcs7_distinguished_name");
  85. desname = (*env)->CallObjectMethod(env, signer->java_signer, mid_PKCS7Signer_name);
  86. if ((*env)->ExceptionCheck(env))
  87. fz_throw_java_and_detach_thread(ctx, env, detach);
  88. if (desname == NULL)
  89. fz_throw_and_detach_thread(ctx, detach, FZ_ERROR_GENERIC, "cannot retrieve distinguished name");
  90. fz_var(name);
  91. fz_try(ctx)
  92. {
  93. name = Memento_label(fz_calloc(ctx, 1, sizeof(*name)), "distinguished name");
  94. name->cn = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_cn);
  95. name->o = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_o);
  96. name->ou = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_ou);
  97. name->email = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_email);
  98. name->c = string_field_to_utfchars(ctx, env, desname, fid_PKCS7DistinguishedName_c);
  99. }
  100. fz_catch(ctx)
  101. {
  102. if (name) fz_free(ctx, name->c);
  103. if (name) fz_free(ctx, name->email);
  104. if (name) fz_free(ctx, name->ou);
  105. if (name) fz_free(ctx, name->o);
  106. if (name) fz_free(ctx, name->cn);
  107. fz_free(ctx, name);
  108. fz_rethrow_and_detach_thread(ctx, detach);
  109. }
  110. jni_detach_thread(detach);
  111. return name;
  112. }
  113. static size_t signer_max_digest_size(fz_context *ctx, pdf_pkcs7_signer *signer_)
  114. {
  115. java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
  116. jboolean detach = JNI_FALSE;
  117. size_t max_digest = 0;
  118. int len;
  119. JNIEnv *env = jni_attach_thread(&detach);
  120. if (env == NULL)
  121. fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in signer_max_digest_size");
  122. /* get the size in bytes we should allow for the digest buffer */
  123. len = (*env)->CallIntMethod(env, signer->java_signer, mid_PKCS7Signer_maxDigest);
  124. if (len < 0)
  125. len = 0;
  126. max_digest = (size_t)len;
  127. if ((*env)->ExceptionCheck(env))
  128. fz_throw_java_and_detach_thread(ctx, env, detach);
  129. jni_detach_thread(detach);
  130. return max_digest;
  131. }
  132. static int signer_create_digest(fz_context *ctx, pdf_pkcs7_signer *signer_, fz_stream *stm, unsigned char *digest, size_t digest_len)
  133. {
  134. java_pkcs7_signer *signer = (java_pkcs7_signer *)signer_;
  135. jobject jsigner = signer->java_signer;
  136. jboolean detach = JNI_FALSE;
  137. jobject jdigest;
  138. jobject jstm;
  139. int result = 1;
  140. JNIEnv *env = jni_attach_thread(&detach);
  141. if (env == NULL)
  142. fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in signer_create_digest");
  143. jstm = to_FitzInputStream(ctx, env, stm);
  144. jdigest = (*env)->CallObjectMethod(env, jsigner, mid_PKCS7Signer_sign, jstm);
  145. if ((*env)->ExceptionCheck(env))
  146. fz_throw_java_and_detach_thread(ctx, env, detach);
  147. if (!jdigest)
  148. fz_throw(ctx, FZ_ERROR_GENERIC, "did not receive digest from signer");
  149. if (digest != NULL)
  150. {
  151. jbyte *src = NULL;
  152. int srclen = 0;
  153. src = (*env)->GetByteArrayElements(env, jdigest, 0);
  154. if (src == NULL)
  155. fz_throw_and_detach_thread(ctx, detach, FZ_ERROR_GENERIC, "cannot get digest");
  156. srclen = (*env)->GetArrayLength(env, jdigest);
  157. if ((size_t)srclen > digest_len)
  158. {
  159. (*env)->ReleaseByteArrayElements(env, jdigest, src, JNI_ABORT);
  160. fz_throw_and_detach_thread(ctx, detach, FZ_ERROR_GENERIC, "digest destination shorter than digest");
  161. }
  162. memcpy(digest, src, srclen);
  163. result = srclen;
  164. (*env)->ReleaseByteArrayElements(env, jdigest, src, JNI_ABORT);
  165. }
  166. jni_detach_thread(detach);
  167. return result;
  168. }
  169. static pdf_pkcs7_signer *pdf_pkcs7_java_signer_create(JNIEnv *env, fz_context *ctx, jobject java_signer)
  170. {
  171. java_pkcs7_signer *signer = Memento_label(fz_calloc(ctx, 1, sizeof(*signer)), "java_pkcs7_signer");
  172. if (signer == NULL) return NULL;
  173. signer->base.keep = signer_keep;
  174. signer->base.drop = signer_drop;
  175. signer->base.get_signing_name = signer_distinguished_name;
  176. signer->base.max_digest_size = signer_max_digest_size;
  177. signer->base.create_digest = signer_create_digest;
  178. signer->refs = 1;
  179. signer->java_signer = (*env)->NewGlobalRef(env, java_signer);
  180. if (signer->java_signer == NULL)
  181. {
  182. fz_free(ctx, signer);
  183. return NULL;
  184. }
  185. return &signer->base;
  186. }
  187. JNIEXPORT jlong JNICALL
  188. FUN(PKCS7Signer_newNative)(JNIEnv *env, jclass cls, jobject jsigner)
  189. {
  190. fz_context *ctx = get_context(env);
  191. pdf_pkcs7_signer *signer = NULL;
  192. if (!ctx) return 0;
  193. if (!jsigner) jni_throw_arg(env, "signer must not be null");
  194. jsigner = (*env)->NewGlobalRef(env, jsigner);
  195. if (!jsigner) jni_throw_arg(env, "unable to get reference to signer");
  196. fz_try(ctx)
  197. signer = pdf_pkcs7_java_signer_create(env, ctx, jsigner);
  198. fz_catch(ctx)
  199. {
  200. (*env)->DeleteGlobalRef(env, jsigner);
  201. jni_rethrow(env, ctx);
  202. }
  203. return jlong_cast(signer);
  204. }
  205. JNIEXPORT void JNICALL
  206. FUN(PKCS7Signer_finalize)(JNIEnv *env, jobject self)
  207. {
  208. fz_context *ctx = get_context(env);
  209. pdf_pkcs7_signer *signer = from_PKCS7Signer_safe(env, self);
  210. if (!ctx || !signer) return;
  211. (*env)->SetLongField(env, self, fid_PKCS7Signer_pointer, 0);
  212. pdf_drop_signer(ctx, signer);
  213. }