1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "NativeBN"
18 
19 #include "JniException.h"
20 #include "jni.h"
21 #include <nativehelper/JNIHelp.h>
22 #include <nativehelper/JniConstants.h>
23 #include <nativehelper/ScopedPrimitiveArray.h>
24 #include <nativehelper/ScopedUtfChars.h>
25 #include <openssl/bn.h>
26 #include <openssl/crypto.h>
27 #include <openssl/err.h>
28 #include <stdio.h>
29 #include <algorithm>
30 #include <memory>
31 
32 struct BN_CTX_Deleter {
operator ()BN_CTX_Deleter33   void operator()(BN_CTX* p) const {
34     BN_CTX_free(p);
35   }
36 };
37 typedef std::unique_ptr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX;
38 
toBigNum(jlong address)39 static BIGNUM* toBigNum(jlong address) {
40   return reinterpret_cast<BIGNUM*>(static_cast<uintptr_t>(address));
41 }
42 
throwException(JNIEnv * env)43 static void throwException(JNIEnv* env) {
44   long error = ERR_get_error();
45   // OpenSSL's error queue may contain multiple errors. Clean up after them.
46   ERR_clear_error();
47 
48   if (error == 0) {
49     // An operation failed but did not push to the error queue. Throw a default
50     // exception.
51     jniThrowException(env, "java/lang/ArithmeticException", "Operation failed");
52     return;
53   }
54 
55   char message[256];
56   ERR_error_string_n(error, message, sizeof(message));
57   int reason = ERR_GET_REASON(error);
58   if (reason == BN_R_DIV_BY_ZERO) {
59     jniThrowException(env, "java/lang/ArithmeticException", "BigInteger division by zero");
60   } else if (reason == BN_R_NO_INVERSE) {
61     jniThrowException(env, "java/lang/ArithmeticException", "BigInteger not invertible");
62   } else if (reason == ERR_R_MALLOC_FAILURE) {
63     jniThrowOutOfMemoryError(env, message);
64   } else {
65     jniThrowException(env, "java/lang/ArithmeticException", message);
66   }
67 }
68 
isValidHandle(JNIEnv * env,jlong handle,const char * message)69 static int isValidHandle(JNIEnv* env, jlong handle, const char* message) {
70   if (handle == 0) {
71     jniThrowNullPointerException(env, message);
72     return JNI_FALSE;
73   }
74   return JNI_TRUE;
75 }
76 
oneValidHandle(JNIEnv * env,jlong a)77 static int oneValidHandle(JNIEnv* env, jlong a) {
78   return isValidHandle(env, a, "Mandatory handle (first) passed as null");
79 }
80 
twoValidHandles(JNIEnv * env,jlong a,jlong b)81 static int twoValidHandles(JNIEnv* env, jlong a, jlong b) {
82   if (!oneValidHandle(env, a)) return JNI_FALSE;
83   return isValidHandle(env, b, "Mandatory handle (second) passed as null");
84 }
85 
threeValidHandles(JNIEnv * env,jlong a,jlong b,jlong c)86 static int threeValidHandles(JNIEnv* env, jlong a, jlong b, jlong c) {
87   if (!twoValidHandles(env, a, b)) return JNI_FALSE;
88   return isValidHandle(env, c, "Mandatory handle (third) passed as null");
89 }
90 
fourValidHandles(JNIEnv * env,jlong a,jlong b,jlong c,jlong d)91 static int fourValidHandles(JNIEnv* env, jlong a, jlong b, jlong c, jlong d) {
92   if (!threeValidHandles(env, a, b, c)) return JNI_FALSE;
93   return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
94 }
95 
NativeBN_BN_new(JNIEnv * env,jclass)96 static jlong NativeBN_BN_new(JNIEnv* env, jclass) {
97   jlong result = static_cast<jlong>(reinterpret_cast<uintptr_t>(BN_new()));
98   if (!result) {
99     throwException(env);
100   }
101   return result;
102 }
103 
NativeBN_getNativeFinalizer(JNIEnv *,jclass)104 static jlong NativeBN_getNativeFinalizer(JNIEnv*, jclass) {
105   return static_cast<jlong>(reinterpret_cast<uintptr_t>(&BN_free));
106 }
107 
NativeBN_BN_free(JNIEnv * env,jclass,jlong a)108 static void NativeBN_BN_free(JNIEnv* env, jclass, jlong a) {
109   if (!oneValidHandle(env, a)) return;
110   BN_free(toBigNum(a));
111 }
112 
NativeBN_BN_cmp(JNIEnv * env,jclass,jlong a,jlong b)113 static int NativeBN_BN_cmp(JNIEnv* env, jclass, jlong a, jlong b) {
114   if (!twoValidHandles(env, a, b)) return 1;
115   return BN_cmp(toBigNum(a), toBigNum(b));
116 }
117 
NativeBN_BN_copy(JNIEnv * env,jclass,jlong to,jlong from)118 static void NativeBN_BN_copy(JNIEnv* env, jclass, jlong to, jlong from) {
119   if (!twoValidHandles(env, to, from)) return;
120   if (!BN_copy(toBigNum(to), toBigNum(from))) {
121     throwException(env);
122   }
123 }
124 
NativeBN_putULongInt(JNIEnv * env,jclass,jlong a0,jlong java_dw,jboolean neg)125 static void NativeBN_putULongInt(JNIEnv* env, jclass, jlong a0, jlong java_dw, jboolean neg) {
126   if (!oneValidHandle(env, a0)) return;
127 
128   uint64_t dw = java_dw;
129   BIGNUM* a = toBigNum(a0);
130 
131   if (!BN_set_u64(a, dw)) {
132     throwException(env);
133     return;
134   }
135 
136   BN_set_negative(a, neg);
137 }
138 
NativeBN_putLongInt(JNIEnv * env,jclass cls,jlong a,jlong dw)139 static void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, jlong dw) {
140   if (dw >= 0) {
141     NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
142   } else {
143     NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
144   }
145 }
146 
NativeBN_BN_dec2bn(JNIEnv * env,jclass,jlong a0,jstring str)147 static int NativeBN_BN_dec2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
148   if (!oneValidHandle(env, a0)) return -1;
149   ScopedUtfChars chars(env, str);
150   if (chars.c_str() == NULL) {
151     return -1;
152   }
153   BIGNUM* a = toBigNum(a0);
154   int result = BN_dec2bn(&a, chars.c_str());
155   if (result == 0) {
156     throwException(env);
157   }
158   return result;
159 }
160 
NativeBN_BN_hex2bn(JNIEnv * env,jclass,jlong a0,jstring str)161 static int NativeBN_BN_hex2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
162   if (!oneValidHandle(env, a0)) return -1;
163   ScopedUtfChars chars(env, str);
164   if (chars.c_str() == NULL) {
165     return -1;
166   }
167   BIGNUM* a = toBigNum(a0);
168   int result = BN_hex2bn(&a, chars.c_str());
169   if (result == 0) {
170     throwException(env);
171   }
172   return result;
173 }
174 
NativeBN_BN_bin2bn(JNIEnv * env,jclass,jbyteArray arr,int len,jboolean neg,jlong ret)175 static void NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, jlong ret) {
176   if (!oneValidHandle(env, ret)) return;
177   ScopedByteArrayRO bytes(env, arr);
178   if (bytes.get() == NULL) {
179     return;
180   }
181   if (!BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret))) {
182     throwException(env);
183     return;
184   }
185 
186   BN_set_negative(toBigNum(ret), neg);
187 }
188 
NativeBN_litEndInts2bn(JNIEnv * env,jclass,jintArray arr,int len,jboolean neg,jlong ret0)189 static void NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, jlong ret0) {
190   if (!oneValidHandle(env, ret0)) return;
191   BIGNUM* ret = toBigNum(ret0);
192 
193   ScopedIntArrayRO scopedArray(env, arr);
194 
195   if (scopedArray.get() == NULL) {
196     return;
197   }
198 
199   // We can simply interpret the little-endian integer stream as a
200   // little-endian byte stream and use BN_le2bn.
201   const uint8_t* tmpBytes = reinterpret_cast<const uint8_t *>(scopedArray.get());
202   size_t numBytes = len * sizeof(int);
203 
204   if (!BN_le2bn(tmpBytes, numBytes, ret)) {
205     throwException(env);
206   }
207 
208   BN_set_negative(ret, neg);
209 }
210 
NativeBN_twosComp2bn(JNIEnv * env,jclass,jbyteArray arr,int bytesLen,jlong ret0)211 static void NativeBN_twosComp2bn(JNIEnv* env, jclass, jbyteArray arr, int bytesLen, jlong ret0) {
212   if (!oneValidHandle(env, ret0)) return;
213   BIGNUM* ret = toBigNum(ret0);
214 
215   ScopedByteArrayRO bytes(env, arr);
216   if (bytes.get() == NULL) {
217     return;
218   }
219 
220   if (bytesLen == 0) {
221     BN_zero(ret);
222     return;
223   }
224 
225   const unsigned char* bytesTmp = reinterpret_cast<const unsigned char*>(bytes.get());
226 
227   if (!BN_bin2bn(bytesTmp, bytesLen, ret)) {
228     throwException(env);
229     return;
230   }
231 
232   // Use the high bit to determine the sign in twos-complement.
233   BN_set_negative(ret, (bytes[0] & 0x80) != 0);
234 
235   if (BN_is_negative(ret)) {
236     // For negative values, BN_bin2bn doesn't interpret the twos-complement
237     // representation, so ret is now (- value - 2^N). We can use nnmod_pow2 to set
238     // ret to (-value).
239     if (!BN_nnmod_pow2(ret, ret, bytesLen * 8)) {
240       throwException(env);
241       return;
242     }
243 
244     // And now we correct the sign.
245     BN_set_negative(ret, 1);
246   }
247 }
248 
NativeBN_longInt(JNIEnv * env,jclass,jlong a0)249 static jlong NativeBN_longInt(JNIEnv* env, jclass, jlong a0) {
250   if (!oneValidHandle(env, a0)) return -1;
251   BIGNUM* a = toBigNum(a0);
252   uint64_t word;
253 
254   if (BN_get_u64(a, &word)) {
255     return BN_is_negative(a) ? -((jlong) word) : word;
256   } else {
257     // This should be unreachable if our caller checks BigInt::twosCompFitsIntoBytes(8)
258     throwException(env);
259     return 0;
260   }
261 }
262 
leadingZerosTrimmed(char * s)263 static char* leadingZerosTrimmed(char* s) {
264     char* p = s;
265     if (*p == '-') {
266         p++;
267         while ((*p == '0') && (*(p + 1) != 0)) { p++; }
268         p--;
269         *p = '-';
270     } else {
271         while ((*p == '0') && (*(p + 1) != 0)) { p++; }
272     }
273     return p;
274 }
275 
NativeBN_BN_bn2dec(JNIEnv * env,jclass,jlong a)276 static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, jlong a) {
277   if (!oneValidHandle(env, a)) return NULL;
278   char* tmpStr = BN_bn2dec(toBigNum(a));
279   if (tmpStr == NULL) {
280     throwException(env);
281     return NULL;
282   }
283   char* retStr = leadingZerosTrimmed(tmpStr);
284   jstring returnJString = env->NewStringUTF(retStr);
285   OPENSSL_free(tmpStr);
286   return returnJString;
287 }
288 
NativeBN_BN_bn2hex(JNIEnv * env,jclass,jlong a)289 static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, jlong a) {
290   if (!oneValidHandle(env, a)) return NULL;
291   char* tmpStr = BN_bn2hex(toBigNum(a));
292   if (tmpStr == NULL) {
293     throwException(env);
294     return NULL;
295   }
296   char* retStr = leadingZerosTrimmed(tmpStr);
297   jstring returnJString = env->NewStringUTF(retStr);
298   OPENSSL_free(tmpStr);
299   return returnJString;
300 }
301 
NativeBN_BN_bn2bin(JNIEnv * env,jclass,jlong a0)302 static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, jlong a0) {
303   if (!oneValidHandle(env, a0)) return NULL;
304   BIGNUM* a = toBigNum(a0);
305   jbyteArray result = env->NewByteArray(BN_num_bytes(a));
306   if (result == NULL) {
307     return NULL;
308   }
309   ScopedByteArrayRW bytes(env, result);
310   if (bytes.get() == NULL) {
311     return NULL;
312   }
313   BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
314   return result;
315 }
316 
NativeBN_bn2litEndInts(JNIEnv * env,jclass,jlong a0)317 static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, jlong a0) {
318   if (!oneValidHandle(env, a0)) return NULL;
319 
320   BIGNUM* a = toBigNum(a0);
321 
322   // The number of integers we need is BN_num_bytes(a) / sizeof(int), rounded up
323   int intLen = (BN_num_bytes(a) + sizeof(int) - 1) / sizeof(int);
324 
325   // Allocate our result with the JNI boilerplate
326   jintArray result = env->NewIntArray(intLen);
327 
328   if (result == NULL) {
329     throwException(env);
330     return NULL;
331   }
332 
333   ScopedIntArrayRW ints(env, result);
334 
335   unsigned int* uints = reinterpret_cast<unsigned int*>(ints.get());
336   if (uints == NULL) {
337     throwException(env);
338     return NULL;
339   }
340 
341   // We can simply interpret a little-endian byte stream as a little-endian integer stream.
342   if (!BN_bn2le_padded(reinterpret_cast<uint8_t*>(uints), intLen * sizeof(int), a)) {
343     throwException(env);
344     return NULL;
345   }
346 
347   return result;
348 }
349 
NativeBN_sign(JNIEnv * env,jclass,jlong a)350 static int NativeBN_sign(JNIEnv* env, jclass, jlong a) {
351   if (!oneValidHandle(env, a)) return -2;
352   if (BN_is_zero(toBigNum(a))) {
353       return 0;
354   } else if (BN_is_negative(toBigNum(a))) {
355     return -1;
356   }
357   return 1;
358 }
359 
NativeBN_BN_set_negative(JNIEnv * env,jclass,jlong b,int n)360 static void NativeBN_BN_set_negative(JNIEnv* env, jclass, jlong b, int n) {
361   if (!oneValidHandle(env, b)) return;
362   BN_set_negative(toBigNum(b), n);
363 }
364 
NativeBN_bitLength(JNIEnv * env,jclass,jlong a0)365 static int NativeBN_bitLength(JNIEnv* env, jclass, jlong a0) {
366   if (!oneValidHandle(env, a0)) return JNI_FALSE;
367   BIGNUM* a = toBigNum(a0);
368 
369   // If a is not negative, we can use BN_num_bits directly.
370   if (!BN_is_negative(a)) {
371     return BN_num_bits(a);
372   }
373 
374   // In the negative case, the number of bits in a is the same as the number of bits in |a|,
375   // except one less when |a| is a power of two.
376   BIGNUM positiveA;
377   BN_init(&positiveA);
378 
379   if (!BN_copy(&positiveA, a)) {
380     BN_free(&positiveA);
381     throwException(env);
382     return -1;
383   }
384 
385   BN_set_negative(&positiveA, false);
386   int numBits = BN_is_pow2(&positiveA) ? BN_num_bits(&positiveA) - 1 : BN_num_bits(&positiveA);
387 
388   BN_free(&positiveA);
389   return numBits;
390 }
391 
NativeBN_BN_is_bit_set(JNIEnv * env,jclass,jlong a,int n)392 static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) {
393   if (!oneValidHandle(env, a)) return JNI_FALSE;
394 
395   // NOTE: this is only called in the positive case, so BN_is_bit_set is fine here.
396   return BN_is_bit_set(toBigNum(a), n) ? JNI_TRUE : JNI_FALSE;
397 }
398 
NativeBN_BN_shift(JNIEnv * env,jclass,jlong r,jlong a,int n)399 static void NativeBN_BN_shift(JNIEnv* env, jclass, jlong r, jlong a, int n) {
400   if (!twoValidHandles(env, r, a)) return;
401   int ok;
402   if (n >= 0) {
403     ok = BN_lshift(toBigNum(r), toBigNum(a), n);
404   } else {
405     ok = BN_rshift(toBigNum(r), toBigNum(a), -n);
406   }
407   if (!ok) {
408     throwException(env);
409   }
410 }
411 
NativeBN_BN_add_word(JNIEnv * env,jclass,jlong a,BN_ULONG w)412 static void NativeBN_BN_add_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
413   if (!oneValidHandle(env, a)) return;
414   if (!BN_add_word(toBigNum(a), w)) {
415     throwException(env);
416   }
417 }
418 
NativeBN_BN_mul_word(JNIEnv * env,jclass,jlong a,BN_ULONG w)419 static void NativeBN_BN_mul_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
420   if (!oneValidHandle(env, a)) return;
421   if (!BN_mul_word(toBigNum(a), w)) {
422     throwException(env);
423   }
424 }
425 
NativeBN_BN_mod_word(JNIEnv * env,jclass,jlong a,BN_ULONG w)426 static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
427   if (!oneValidHandle(env, a)) return 0;
428   BN_ULONG result = BN_mod_word(toBigNum(a), w);
429   if (result == (BN_ULONG)-1) {
430     throwException(env);
431   }
432   return result;
433 }
434 
NativeBN_BN_add(JNIEnv * env,jclass,jlong r,jlong a,jlong b)435 static void NativeBN_BN_add(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
436   if (!threeValidHandles(env, r, a, b)) return;
437   if (!BN_add(toBigNum(r), toBigNum(a), toBigNum(b))) {
438     throwException(env);
439   }
440 }
441 
NativeBN_BN_sub(JNIEnv * env,jclass,jlong r,jlong a,jlong b)442 static void NativeBN_BN_sub(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
443   if (!threeValidHandles(env, r, a, b)) return;
444   if (!BN_sub(toBigNum(r), toBigNum(a), toBigNum(b))) {
445     throwException(env);
446   }
447 }
448 
NativeBN_BN_gcd(JNIEnv * env,jclass,jlong r,jlong a,jlong b)449 static void NativeBN_BN_gcd(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
450   if (!threeValidHandles(env, r, a, b)) return;
451   Unique_BN_CTX ctx(BN_CTX_new());
452   if (!BN_gcd(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get())) {
453     throwException(env);
454   }
455 }
456 
NativeBN_BN_mul(JNIEnv * env,jclass,jlong r,jlong a,jlong b)457 static void NativeBN_BN_mul(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
458   if (!threeValidHandles(env, r, a, b)) return;
459   Unique_BN_CTX ctx(BN_CTX_new());
460   if (!BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get())) {
461     throwException(env);
462   }
463 }
464 
NativeBN_BN_exp(JNIEnv * env,jclass,jlong r,jlong a,jlong p)465 static void NativeBN_BN_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p) {
466   if (!threeValidHandles(env, r, a, p)) return;
467   Unique_BN_CTX ctx(BN_CTX_new());
468   if (!BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get())) {
469     throwException(env);
470   }
471 }
472 
NativeBN_BN_div(JNIEnv * env,jclass,jlong dv,jlong rem,jlong m,jlong d)473 static void NativeBN_BN_div(JNIEnv* env, jclass, jlong dv, jlong rem, jlong m, jlong d) {
474   if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return;
475   Unique_BN_CTX ctx(BN_CTX_new());
476   if (!BN_div(toBigNum(dv), toBigNum(rem), toBigNum(m), toBigNum(d), ctx.get())) {
477     throwException(env);
478   }
479 }
480 
NativeBN_BN_nnmod(JNIEnv * env,jclass,jlong r,jlong a,jlong m)481 static void NativeBN_BN_nnmod(JNIEnv* env, jclass, jlong r, jlong a, jlong m) {
482   if (!threeValidHandles(env, r, a, m)) return;
483   Unique_BN_CTX ctx(BN_CTX_new());
484   if (!BN_nnmod(toBigNum(r), toBigNum(a), toBigNum(m), ctx.get())) {
485     throwException(env);
486   }
487 }
488 
NativeBN_BN_mod_exp(JNIEnv * env,jclass,jlong r,jlong a,jlong p,jlong m)489 static void NativeBN_BN_mod_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p, jlong m) {
490   if (!fourValidHandles(env, r, a, p, m)) return;
491   Unique_BN_CTX ctx(BN_CTX_new());
492   if (!BN_mod_exp(toBigNum(r), toBigNum(a), toBigNum(p), toBigNum(m), ctx.get())) {
493     throwException(env);
494   }
495 }
496 
NativeBN_BN_mod_inverse(JNIEnv * env,jclass,jlong ret,jlong a,jlong n)497 static void NativeBN_BN_mod_inverse(JNIEnv* env, jclass, jlong ret, jlong a, jlong n) {
498   if (!threeValidHandles(env, ret, a, n)) return;
499   Unique_BN_CTX ctx(BN_CTX_new());
500   if (!BN_mod_inverse(toBigNum(ret), toBigNum(a), toBigNum(n), ctx.get())) {
501     throwException(env);
502   }
503 }
504 
NativeBN_BN_generate_prime_ex(JNIEnv * env,jclass,jlong ret,int bits,jboolean safe,jlong add,jlong rem)505 static void NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, jlong ret, int bits,
506                                           jboolean safe, jlong add, jlong rem) {
507   if (!oneValidHandle(env, ret)) return;
508   if (!BN_generate_prime_ex(toBigNum(ret), bits, safe, toBigNum(add), toBigNum(rem),
509                             NULL)) {
510     throwException(env);
511   }
512 }
513 
NativeBN_BN_primality_test(JNIEnv * env,jclass,jlong candidate,int checks,jboolean do_trial_decryption)514 static jboolean NativeBN_BN_primality_test(JNIEnv* env, jclass, jlong candidate, int checks,
515                                            jboolean do_trial_decryption) {
516   if (!oneValidHandle(env, candidate)) return JNI_FALSE;
517   Unique_BN_CTX ctx(BN_CTX_new());
518   int is_probably_prime;
519   if (!BN_primality_test(&is_probably_prime, toBigNum(candidate), checks, ctx.get(),
520                          do_trial_decryption, NULL)) {
521     throwException(env);
522     return JNI_FALSE;
523   }
524   return is_probably_prime ? JNI_TRUE : JNI_FALSE;
525 }
526 
527 static JNINativeMethod gMethods[] = {
528    NATIVE_METHOD(NativeBN, BN_add, "(JJJ)V"),
529    NATIVE_METHOD(NativeBN, BN_add_word, "(JI)V"),
530    NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZJ)V"),
531    NATIVE_METHOD(NativeBN, BN_bn2bin, "(J)[B"),
532    NATIVE_METHOD(NativeBN, BN_bn2dec, "(J)Ljava/lang/String;"),
533    NATIVE_METHOD(NativeBN, BN_bn2hex, "(J)Ljava/lang/String;"),
534    NATIVE_METHOD(NativeBN, BN_cmp, "(JJ)I"),
535    NATIVE_METHOD(NativeBN, BN_copy, "(JJ)V"),
536    NATIVE_METHOD(NativeBN, BN_dec2bn, "(JLjava/lang/String;)I"),
537    NATIVE_METHOD(NativeBN, BN_div, "(JJJJ)V"),
538    NATIVE_METHOD(NativeBN, BN_exp, "(JJJ)V"),
539    NATIVE_METHOD(NativeBN, BN_free, "(J)V"),
540    NATIVE_METHOD(NativeBN, BN_gcd, "(JJJ)V"),
541    NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(JIZJJ)V"),
542    NATIVE_METHOD(NativeBN, BN_hex2bn, "(JLjava/lang/String;)I"),
543    NATIVE_METHOD(NativeBN, BN_is_bit_set, "(JI)Z"),
544    NATIVE_METHOD(NativeBN, BN_primality_test, "(JIZ)Z"),
545    NATIVE_METHOD(NativeBN, BN_mod_exp, "(JJJJ)V"),
546    NATIVE_METHOD(NativeBN, BN_mod_inverse, "(JJJ)V"),
547    NATIVE_METHOD(NativeBN, BN_mod_word, "(JI)I"),
548    NATIVE_METHOD(NativeBN, BN_mul, "(JJJ)V"),
549    NATIVE_METHOD(NativeBN, BN_mul_word, "(JI)V"),
550    NATIVE_METHOD(NativeBN, BN_new, "()J"),
551    NATIVE_METHOD(NativeBN, BN_nnmod, "(JJJ)V"),
552    NATIVE_METHOD(NativeBN, BN_set_negative, "(JI)V"),
553    NATIVE_METHOD(NativeBN, BN_shift, "(JJI)V"),
554    NATIVE_METHOD(NativeBN, BN_sub, "(JJJ)V"),
555    NATIVE_METHOD(NativeBN, bitLength, "(J)I"),
556    NATIVE_METHOD(NativeBN, bn2litEndInts, "(J)[I"),
557    NATIVE_METHOD(NativeBN, getNativeFinalizer, "()J"),
558    NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZJ)V"),
559    NATIVE_METHOD(NativeBN, longInt, "(J)J"),
560    NATIVE_METHOD(NativeBN, putLongInt, "(JJ)V"),
561    NATIVE_METHOD(NativeBN, putULongInt, "(JJZ)V"),
562    NATIVE_METHOD(NativeBN, sign, "(J)I"),
563    NATIVE_METHOD(NativeBN, twosComp2bn, "([BIJ)V"),
564 };
register_java_math_NativeBN(JNIEnv * env)565 void register_java_math_NativeBN(JNIEnv* env) {
566     jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
567 }
568