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