• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "JNIHelp.h"
20 #include "JniConstants.h"
21 #include "JniException.h"
22 #include "ScopedPrimitiveArray.h"
23 #include "ScopedUtfChars.h"
24 #include "jni.h"
25 #include <openssl/bn.h>
26 #include <openssl/crypto.h>
27 #include <openssl/err.h>
28 #include <stdio.h>
29 #include <memory>
30 
31 #if defined(OPENSSL_IS_BORINGSSL)
32 /* BoringSSL no longer exports |bn_check_top|. */
bn_check_top(const BIGNUM * bn)33 static void bn_check_top(const BIGNUM* bn) {
34   /* This asserts that |bn->top| (which contains the number of elements of
35    * |bn->d| that are valid) is minimal. In other words, that there aren't
36    * superfluous zeros. */
37   if (bn != NULL && bn->top != 0 && bn->d[bn->top-1] == 0) {
38     abort();
39   }
40 }
41 #endif
42 
43 struct BN_CTX_Deleter {
operator ()BN_CTX_Deleter44   void operator()(BN_CTX* p) const {
45     BN_CTX_free(p);
46   }
47 };
48 typedef std::unique_ptr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX;
49 
toBigNum(jlong address)50 static BIGNUM* toBigNum(jlong address) {
51   return reinterpret_cast<BIGNUM*>(static_cast<uintptr_t>(address));
52 }
53 
throwExceptionIfNecessary(JNIEnv * env)54 static bool throwExceptionIfNecessary(JNIEnv* env) {
55   long error = ERR_get_error();
56   if (error == 0) {
57     return false;
58   }
59   char message[256];
60   ERR_error_string_n(error, message, sizeof(message));
61   int reason = ERR_GET_REASON(error);
62   if (reason == BN_R_DIV_BY_ZERO) {
63     jniThrowException(env, "java/lang/ArithmeticException", "BigInteger division by zero");
64   } else if (reason == BN_R_NO_INVERSE) {
65     jniThrowException(env, "java/lang/ArithmeticException", "BigInteger not invertible");
66   } else if (reason == ERR_R_MALLOC_FAILURE) {
67     jniThrowOutOfMemoryError(env, message);
68   } else {
69     jniThrowException(env, "java/lang/ArithmeticException", message);
70   }
71   return true;
72 }
73 
isValidHandle(JNIEnv * env,jlong handle,const char * message)74 static int isValidHandle(JNIEnv* env, jlong handle, const char* message) {
75   if (handle == 0) {
76     jniThrowNullPointerException(env, message);
77     return JNI_FALSE;
78   }
79   return JNI_TRUE;
80 }
81 
oneValidHandle(JNIEnv * env,jlong a)82 static int oneValidHandle(JNIEnv* env, jlong a) {
83   return isValidHandle(env, a, "Mandatory handle (first) passed as null");
84 }
85 
twoValidHandles(JNIEnv * env,jlong a,jlong b)86 static int twoValidHandles(JNIEnv* env, jlong a, jlong b) {
87   if (!oneValidHandle(env, a)) return JNI_FALSE;
88   return isValidHandle(env, b, "Mandatory handle (second) passed as null");
89 }
90 
threeValidHandles(JNIEnv * env,jlong a,jlong b,jlong c)91 static int threeValidHandles(JNIEnv* env, jlong a, jlong b, jlong c) {
92   if (!twoValidHandles(env, a, b)) return JNI_FALSE;
93   return isValidHandle(env, c, "Mandatory handle (third) passed as null");
94 }
95 
fourValidHandles(JNIEnv * env,jlong a,jlong b,jlong c,jlong d)96 static int fourValidHandles(JNIEnv* env, jlong a, jlong b, jlong c, jlong d) {
97   if (!threeValidHandles(env, a, b, c)) return JNI_FALSE;
98   return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
99 }
100 
NativeBN_BN_new(JNIEnv * env,jclass)101 static jlong NativeBN_BN_new(JNIEnv* env, jclass) {
102   jlong result = static_cast<jlong>(reinterpret_cast<uintptr_t>(BN_new()));
103   throwExceptionIfNecessary(env);
104   return result;
105 }
106 
NativeBN_getNativeFinalizer(JNIEnv *,jclass)107 static jlong NativeBN_getNativeFinalizer(JNIEnv*, jclass) {
108   return static_cast<jlong>(reinterpret_cast<uintptr_t>(&BN_free));
109 }
110 
NativeBN_BN_free(JNIEnv * env,jclass,jlong a)111 static void NativeBN_BN_free(JNIEnv* env, jclass, jlong a) {
112   if (!oneValidHandle(env, a)) return;
113   BN_free(toBigNum(a));
114 }
115 
NativeBN_BN_cmp(JNIEnv * env,jclass,jlong a,jlong b)116 static int NativeBN_BN_cmp(JNIEnv* env, jclass, jlong a, jlong b) {
117   if (!twoValidHandles(env, a, b)) return 1;
118   return BN_cmp(toBigNum(a), toBigNum(b));
119 }
120 
NativeBN_BN_copy(JNIEnv * env,jclass,jlong to,jlong from)121 static void NativeBN_BN_copy(JNIEnv* env, jclass, jlong to, jlong from) {
122   if (!twoValidHandles(env, to, from)) return;
123   BN_copy(toBigNum(to), toBigNum(from));
124   throwExceptionIfNecessary(env);
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   int ok;
133 
134   static_assert(sizeof(dw) == sizeof(BN_ULONG) ||
135                 sizeof(dw) == 2*sizeof(BN_ULONG), "Unknown BN configuration");
136 
137   if (sizeof(dw) == sizeof(BN_ULONG)) {
138     ok = BN_set_word(a, dw);
139   } else if (sizeof(dw) == 2 * sizeof(BN_ULONG)) {
140     ok = (bn_wexpand(a, 2) != NULL);
141     if (ok) {
142       a->d[0] = dw;
143       a->d[1] = dw >> 32;
144       a->top = 2;
145       bn_correct_top(a);
146     }
147   }
148 
149   BN_set_negative(a, neg);
150 
151   if (!ok) {
152     throwExceptionIfNecessary(env);
153   }
154 }
155 
NativeBN_putLongInt(JNIEnv * env,jclass cls,jlong a,jlong dw)156 static void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, jlong dw) {
157   if (dw >= 0) {
158     NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
159   } else {
160     NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
161   }
162 }
163 
NativeBN_BN_dec2bn(JNIEnv * env,jclass,jlong a0,jstring str)164 static int NativeBN_BN_dec2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
165   if (!oneValidHandle(env, a0)) return -1;
166   ScopedUtfChars chars(env, str);
167   if (chars.c_str() == NULL) {
168     return -1;
169   }
170   BIGNUM* a = toBigNum(a0);
171   int result = BN_dec2bn(&a, chars.c_str());
172   throwExceptionIfNecessary(env);
173   return result;
174 }
175 
NativeBN_BN_hex2bn(JNIEnv * env,jclass,jlong a0,jstring str)176 static int NativeBN_BN_hex2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
177   if (!oneValidHandle(env, a0)) return -1;
178   ScopedUtfChars chars(env, str);
179   if (chars.c_str() == NULL) {
180     return -1;
181   }
182   BIGNUM* a = toBigNum(a0);
183   int result = BN_hex2bn(&a, chars.c_str());
184   throwExceptionIfNecessary(env);
185   return result;
186 }
187 
NativeBN_BN_bin2bn(JNIEnv * env,jclass,jbyteArray arr,int len,jboolean neg,jlong ret)188 static void NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, jlong ret) {
189   if (!oneValidHandle(env, ret)) return;
190   ScopedByteArrayRO bytes(env, arr);
191   if (bytes.get() == NULL) {
192     return;
193   }
194   BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret));
195   if (!throwExceptionIfNecessary(env) && neg) {
196     BN_set_negative(toBigNum(ret), true);
197   }
198 }
199 
200 /**
201  * Note:
202  * This procedure directly writes the internal representation of BIGNUMs.
203  * We do so as there is no direct interface based on Little Endian Integer Arrays.
204  * Also note that the same representation is used in the Cordoba Java Implementation of BigIntegers,
205  *        whereof certain functionality is still being used.
206  */
NativeBN_litEndInts2bn(JNIEnv * env,jclass,jintArray arr,int len,jboolean neg,jlong ret0)207 static void NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, jlong ret0) {
208   if (!oneValidHandle(env, ret0)) return;
209   BIGNUM* ret = toBigNum(ret0);
210   bn_check_top(ret);
211   if (len > 0) {
212     ScopedIntArrayRO scopedArray(env, arr);
213     if (scopedArray.get() == NULL) {
214       return;
215     }
216 #ifdef __LP64__
217     const int wlen = (len + 1) / 2;
218 #else
219     const int wlen = len;
220 #endif
221     const unsigned int* tmpInts = reinterpret_cast<const unsigned int*>(scopedArray.get());
222     if ((tmpInts != NULL) && (bn_wexpand(ret, wlen) != NULL)) {
223 #ifdef __LP64__
224       if (len % 2) {
225         ret->d[wlen - 1] = tmpInts[--len];
226       }
227       if (len > 0) {
228         for (int i = len - 2; i >= 0; i -= 2) {
229           ret->d[i/2] = ((unsigned long long)tmpInts[i+1] << 32) | tmpInts[i];
230         }
231       }
232 #else
233       int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
234 #endif
235       ret->top = wlen;
236       ret->neg = neg;
237       // need to call this due to clear byte at top if avoiding
238       // having the top bit set (-ve number)
239       // Basically get rid of top zero ints:
240       bn_correct_top(ret);
241     } else {
242       throwExceptionIfNecessary(env);
243     }
244   } else { // (len = 0) means value = 0 and sign will be 0, too.
245     ret->top = 0;
246   }
247 }
248 
249 
250 #ifdef __LP64__
251 #define BYTES2ULONG(bytes, k) \
252     ((bytes[k + 7] & 0xffULL)       | (bytes[k + 6] & 0xffULL) <<  8 | (bytes[k + 5] & 0xffULL) << 16 | (bytes[k + 4] & 0xffULL) << 24 | \
253      (bytes[k + 3] & 0xffULL) << 32 | (bytes[k + 2] & 0xffULL) << 40 | (bytes[k + 1] & 0xffULL) << 48 | (bytes[k + 0] & 0xffULL) << 56)
254 #else
255 #define BYTES2ULONG(bytes, k) \
256     ((bytes[k + 3] & 0xff) | (bytes[k + 2] & 0xff) << 8 | (bytes[k + 1] & 0xff) << 16 | (bytes[k + 0] & 0xff) << 24)
257 #endif
negBigEndianBytes2bn(JNIEnv *,jclass,const unsigned char * bytes,int bytesLen,jlong ret0)258 static void negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, jlong ret0) {
259   BIGNUM* ret = toBigNum(ret0);
260 
261   bn_check_top(ret);
262   // FIXME: assert bytesLen > 0
263   int wLen = (bytesLen + sizeof(BN_ULONG) - 1) / sizeof(BN_ULONG);
264   int firstNonzeroDigit = -2;
265   if (bn_wexpand(ret, wLen) != NULL) {
266     BN_ULONG* d = ret->d;
267     BN_ULONG di;
268     ret->top = wLen;
269     int highBytes = bytesLen % sizeof(BN_ULONG);
270     int k = bytesLen;
271     // Put bytes to the int array starting from the end of the byte array
272     int i = 0;
273     while (k > highBytes) {
274       k -= sizeof(BN_ULONG);
275       di = BYTES2ULONG(bytes, k);
276       if (di != 0) {
277         d[i] = -di;
278         firstNonzeroDigit = i;
279         i++;
280         while (k > highBytes) {
281           k -= sizeof(BN_ULONG);
282           d[i] = ~BYTES2ULONG(bytes, k);
283           i++;
284         }
285         break;
286       } else {
287         d[i] = 0;
288         i++;
289       }
290     }
291     if (highBytes != 0) {
292       di = -1;
293       // Put the first bytes in the highest element of the int array
294       if (firstNonzeroDigit != -2) {
295         for (k = 0; k < highBytes; k++) {
296           di = (di << 8) | (bytes[k] & 0xFF);
297         }
298         d[i] = ~di;
299       } else {
300         for (k = 0; k < highBytes; k++) {
301           di = (di << 8) | (bytes[k] & 0xFF);
302         }
303         d[i] = -di;
304       }
305     }
306     // The top may have superfluous zeros, so fix it.
307     bn_correct_top(ret);
308   }
309 }
310 
NativeBN_twosComp2bn(JNIEnv * env,jclass cls,jbyteArray arr,int bytesLen,jlong ret0)311 static void NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, jlong ret0) {
312   if (!oneValidHandle(env, ret0)) return;
313   BIGNUM* ret = toBigNum(ret0);
314 
315   ScopedByteArrayRO bytes(env, arr);
316   if (bytes.get() == NULL) {
317     return;
318   }
319   const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
320   if ((bytes[0] & 0X80) == 0) { // Positive value!
321     //
322     // We can use the existing BN implementation for unsigned big endian bytes:
323     //
324     BN_bin2bn(s, bytesLen, ret);
325     BN_set_negative(ret, false);
326   } else { // Negative value!
327     //
328     // We need to apply two's complement:
329     //
330     negBigEndianBytes2bn(env, cls, s, bytesLen, ret0);
331     BN_set_negative(ret, true);
332   }
333   throwExceptionIfNecessary(env);
334 }
335 
NativeBN_longInt(JNIEnv * env,jclass,jlong a0)336 static jlong NativeBN_longInt(JNIEnv* env, jclass, jlong a0) {
337   if (!oneValidHandle(env, a0)) return -1;
338 
339   BIGNUM* a = toBigNum(a0);
340   bn_check_top(a);
341   int wLen = a->top;
342   if (wLen == 0) {
343     return 0;
344   }
345 
346 #ifdef __LP64__
347   jlong result = a->d[0];
348 #else
349   jlong result = static_cast<jlong>(a->d[0]) & 0xffffffff;
350   if (wLen > 1) {
351     result |= static_cast<jlong>(a->d[1]) << 32;
352   }
353 #endif
354   return a->neg ? -result : result;
355 }
356 
leadingZerosTrimmed(char * s)357 static char* leadingZerosTrimmed(char* s) {
358     char* p = s;
359     if (*p == '-') {
360         p++;
361         while ((*p == '0') && (*(p + 1) != 0)) { p++; }
362         p--;
363         *p = '-';
364     } else {
365         while ((*p == '0') && (*(p + 1) != 0)) { p++; }
366     }
367     return p;
368 }
369 
NativeBN_BN_bn2dec(JNIEnv * env,jclass,jlong a)370 static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, jlong a) {
371   if (!oneValidHandle(env, a)) return NULL;
372   char* tmpStr = BN_bn2dec(toBigNum(a));
373   if (tmpStr == NULL) {
374     return NULL;
375   }
376   char* retStr = leadingZerosTrimmed(tmpStr);
377   jstring returnJString = env->NewStringUTF(retStr);
378   OPENSSL_free(tmpStr);
379   return returnJString;
380 }
381 
NativeBN_BN_bn2hex(JNIEnv * env,jclass,jlong a)382 static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, jlong a) {
383   if (!oneValidHandle(env, a)) return NULL;
384   char* tmpStr = BN_bn2hex(toBigNum(a));
385   if (tmpStr == NULL) {
386     return NULL;
387   }
388   char* retStr = leadingZerosTrimmed(tmpStr);
389   jstring returnJString = env->NewStringUTF(retStr);
390   OPENSSL_free(tmpStr);
391   return returnJString;
392 }
393 
NativeBN_BN_bn2bin(JNIEnv * env,jclass,jlong a0)394 static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, jlong a0) {
395   if (!oneValidHandle(env, a0)) return NULL;
396   BIGNUM* a = toBigNum(a0);
397   jbyteArray result = env->NewByteArray(BN_num_bytes(a));
398   if (result == NULL) {
399     return NULL;
400   }
401   ScopedByteArrayRW bytes(env, result);
402   if (bytes.get() == NULL) {
403     return NULL;
404   }
405   BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
406   return result;
407 }
408 
NativeBN_bn2litEndInts(JNIEnv * env,jclass,jlong a0)409 static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, jlong a0) {
410   if (!oneValidHandle(env, a0)) return NULL;
411   BIGNUM* a = toBigNum(a0);
412   bn_check_top(a);
413   int wLen = a->top;
414   if (wLen == 0) {
415     return NULL;
416   }
417   jintArray result = env->NewIntArray(wLen * sizeof(BN_ULONG)/sizeof(unsigned int));
418   if (result == NULL) {
419     return NULL;
420   }
421   ScopedIntArrayRW ints(env, result);
422   if (ints.get() == NULL) {
423     return NULL;
424   }
425   unsigned int* uints = reinterpret_cast<unsigned int*>(ints.get());
426   if (uints == NULL) {
427     return NULL;
428   }
429 #ifdef __LP64__
430   int i = wLen; do { i--; uints[i*2+1] = a->d[i] >> 32; uints[i*2] = a->d[i]; } while (i > 0);
431 #else
432   int i = wLen; do { i--; uints[i] = a->d[i]; } while (i > 0);
433 #endif
434   return result;
435 }
436 
NativeBN_sign(JNIEnv * env,jclass,jlong a)437 static int NativeBN_sign(JNIEnv* env, jclass, jlong a) {
438   if (!oneValidHandle(env, a)) return -2;
439   if (BN_is_zero(toBigNum(a))) {
440       return 0;
441   } else if (BN_is_negative(toBigNum(a))) {
442     return -1;
443   }
444   return 1;
445 }
446 
NativeBN_BN_set_negative(JNIEnv * env,jclass,jlong b,int n)447 static void NativeBN_BN_set_negative(JNIEnv* env, jclass, jlong b, int n) {
448   if (!oneValidHandle(env, b)) return;
449   BN_set_negative(toBigNum(b), n);
450 }
451 
NativeBN_bitLength(JNIEnv * env,jclass,jlong a0)452 static int NativeBN_bitLength(JNIEnv* env, jclass, jlong a0) {
453   if (!oneValidHandle(env, a0)) return JNI_FALSE;
454   BIGNUM* a = toBigNum(a0);
455   bn_check_top(a);
456   int wLen = a->top;
457   if (wLen == 0) return 0;
458   BN_ULONG* d = a->d;
459   int i = wLen - 1;
460   BN_ULONG msd = d[i]; // most significant digit
461   if (a->neg) {
462     // Handle negative values correctly:
463     // i.e. decrement the msd if all other digits are 0:
464     // while ((i > 0) && (d[i] != 0)) { i--; }
465     do { i--; } while (!((i < 0) || (d[i] != 0)));
466     if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
467   }
468   return (wLen - 1) * sizeof(BN_ULONG) * 8 + BN_num_bits_word(msd);
469 }
470 
NativeBN_BN_is_bit_set(JNIEnv * env,jclass,jlong a,int n)471 static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) {
472   if (!oneValidHandle(env, a)) return JNI_FALSE;
473   return BN_is_bit_set(toBigNum(a), n);
474 }
475 
NativeBN_BN_shift(JNIEnv * env,jclass,jlong r,jlong a,int n)476 static void NativeBN_BN_shift(JNIEnv* env, jclass, jlong r, jlong a, int n) {
477   if (!twoValidHandles(env, r, a)) return;
478   if (n >= 0) {
479     BN_lshift(toBigNum(r), toBigNum(a), n);
480   } else {
481     BN_rshift(toBigNum(r), toBigNum(a), -n);
482   }
483   throwExceptionIfNecessary(env);
484 }
485 
NativeBN_BN_add_word(JNIEnv * env,jclass,jlong a,BN_ULONG w)486 static void NativeBN_BN_add_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
487   if (!oneValidHandle(env, a)) return;
488   BN_add_word(toBigNum(a), w);
489   throwExceptionIfNecessary(env);
490 }
491 
NativeBN_BN_mul_word(JNIEnv * env,jclass,jlong a,BN_ULONG w)492 static void NativeBN_BN_mul_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
493   if (!oneValidHandle(env, a)) return;
494   BN_mul_word(toBigNum(a), w);
495   throwExceptionIfNecessary(env);
496 }
497 
NativeBN_BN_mod_word(JNIEnv * env,jclass,jlong a,BN_ULONG w)498 static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
499   if (!oneValidHandle(env, a)) return 0;
500   int result = BN_mod_word(toBigNum(a), w);
501   throwExceptionIfNecessary(env);
502   return result;
503 }
504 
NativeBN_BN_add(JNIEnv * env,jclass,jlong r,jlong a,jlong b)505 static void NativeBN_BN_add(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
506   if (!threeValidHandles(env, r, a, b)) return;
507   BN_add(toBigNum(r), toBigNum(a), toBigNum(b));
508   throwExceptionIfNecessary(env);
509 }
510 
NativeBN_BN_sub(JNIEnv * env,jclass,jlong r,jlong a,jlong b)511 static void NativeBN_BN_sub(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
512   if (!threeValidHandles(env, r, a, b)) return;
513   BN_sub(toBigNum(r), toBigNum(a), toBigNum(b));
514   throwExceptionIfNecessary(env);
515 }
516 
NativeBN_BN_gcd(JNIEnv * env,jclass,jlong r,jlong a,jlong b)517 static void NativeBN_BN_gcd(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
518   if (!threeValidHandles(env, r, a, b)) return;
519   Unique_BN_CTX ctx(BN_CTX_new());
520   BN_gcd(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
521   throwExceptionIfNecessary(env);
522 }
523 
NativeBN_BN_mul(JNIEnv * env,jclass,jlong r,jlong a,jlong b)524 static void NativeBN_BN_mul(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
525   if (!threeValidHandles(env, r, a, b)) return;
526   Unique_BN_CTX ctx(BN_CTX_new());
527   BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
528   throwExceptionIfNecessary(env);
529 }
530 
NativeBN_BN_exp(JNIEnv * env,jclass,jlong r,jlong a,jlong p)531 static void NativeBN_BN_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p) {
532   if (!threeValidHandles(env, r, a, p)) return;
533   Unique_BN_CTX ctx(BN_CTX_new());
534   BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get());
535   throwExceptionIfNecessary(env);
536 }
537 
NativeBN_BN_div(JNIEnv * env,jclass,jlong dv,jlong rem,jlong m,jlong d)538 static void NativeBN_BN_div(JNIEnv* env, jclass, jlong dv, jlong rem, jlong m, jlong d) {
539   if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return;
540   Unique_BN_CTX ctx(BN_CTX_new());
541   BN_div(toBigNum(dv), toBigNum(rem), toBigNum(m), toBigNum(d), ctx.get());
542   throwExceptionIfNecessary(env);
543 }
544 
NativeBN_BN_nnmod(JNIEnv * env,jclass,jlong r,jlong a,jlong m)545 static void NativeBN_BN_nnmod(JNIEnv* env, jclass, jlong r, jlong a, jlong m) {
546   if (!threeValidHandles(env, r, a, m)) return;
547   Unique_BN_CTX ctx(BN_CTX_new());
548   BN_nnmod(toBigNum(r), toBigNum(a), toBigNum(m), ctx.get());
549   throwExceptionIfNecessary(env);
550 }
551 
NativeBN_BN_mod_exp(JNIEnv * env,jclass,jlong r,jlong a,jlong p,jlong m)552 static void NativeBN_BN_mod_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p, jlong m) {
553   if (!fourValidHandles(env, r, a, p, m)) return;
554   Unique_BN_CTX ctx(BN_CTX_new());
555   BN_mod_exp(toBigNum(r), toBigNum(a), toBigNum(p), toBigNum(m), ctx.get());
556   throwExceptionIfNecessary(env);
557 }
558 
NativeBN_BN_mod_inverse(JNIEnv * env,jclass,jlong ret,jlong a,jlong n)559 static void NativeBN_BN_mod_inverse(JNIEnv* env, jclass, jlong ret, jlong a, jlong n) {
560   if (!threeValidHandles(env, ret, a, n)) return;
561   Unique_BN_CTX ctx(BN_CTX_new());
562   BN_mod_inverse(toBigNum(ret), toBigNum(a), toBigNum(n), ctx.get());
563   throwExceptionIfNecessary(env);
564 }
565 
NativeBN_BN_generate_prime_ex(JNIEnv * env,jclass,jlong ret,int bits,jboolean safe,jlong add,jlong rem,jlong cb)566 static void NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, jlong ret, int bits,
567                                           jboolean safe, jlong add, jlong rem, jlong cb) {
568   if (!oneValidHandle(env, ret)) return;
569   BN_generate_prime_ex(toBigNum(ret), bits, safe, toBigNum(add), toBigNum(rem),
570                        reinterpret_cast<BN_GENCB*>(cb));
571   throwExceptionIfNecessary(env);
572 }
573 
NativeBN_BN_is_prime_ex(JNIEnv * env,jclass,jlong p,int nchecks,jlong cb)574 static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, jlong p, int nchecks, jlong cb) {
575   if (!oneValidHandle(env, p)) return JNI_FALSE;
576   Unique_BN_CTX ctx(BN_CTX_new());
577   return BN_is_prime_ex(toBigNum(p), nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
578 }
579 
580 static JNINativeMethod gMethods[] = {
581    NATIVE_METHOD(NativeBN, BN_add, "(JJJ)V"),
582    NATIVE_METHOD(NativeBN, BN_add_word, "(JI)V"),
583    NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZJ)V"),
584    NATIVE_METHOD(NativeBN, BN_bn2bin, "(J)[B"),
585    NATIVE_METHOD(NativeBN, BN_bn2dec, "(J)Ljava/lang/String;"),
586    NATIVE_METHOD(NativeBN, BN_bn2hex, "(J)Ljava/lang/String;"),
587    NATIVE_METHOD(NativeBN, BN_cmp, "(JJ)I"),
588    NATIVE_METHOD(NativeBN, BN_copy, "(JJ)V"),
589    NATIVE_METHOD(NativeBN, BN_dec2bn, "(JLjava/lang/String;)I"),
590    NATIVE_METHOD(NativeBN, BN_div, "(JJJJ)V"),
591    NATIVE_METHOD(NativeBN, BN_exp, "(JJJ)V"),
592    NATIVE_METHOD(NativeBN, BN_free, "(J)V"),
593    NATIVE_METHOD(NativeBN, BN_gcd, "(JJJ)V"),
594    NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(JIZJJJ)V"),
595    NATIVE_METHOD(NativeBN, BN_hex2bn, "(JLjava/lang/String;)I"),
596    NATIVE_METHOD(NativeBN, BN_is_bit_set, "(JI)Z"),
597    NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(JIJ)Z"),
598    NATIVE_METHOD(NativeBN, BN_mod_exp, "(JJJJ)V"),
599    NATIVE_METHOD(NativeBN, BN_mod_inverse, "(JJJ)V"),
600    NATIVE_METHOD(NativeBN, BN_mod_word, "(JI)I"),
601    NATIVE_METHOD(NativeBN, BN_mul, "(JJJ)V"),
602    NATIVE_METHOD(NativeBN, BN_mul_word, "(JI)V"),
603    NATIVE_METHOD(NativeBN, BN_new, "()J"),
604    NATIVE_METHOD(NativeBN, BN_nnmod, "(JJJ)V"),
605    NATIVE_METHOD(NativeBN, BN_set_negative, "(JI)V"),
606    NATIVE_METHOD(NativeBN, BN_shift, "(JJI)V"),
607    NATIVE_METHOD(NativeBN, BN_sub, "(JJJ)V"),
608    NATIVE_METHOD(NativeBN, bitLength, "(J)I"),
609    NATIVE_METHOD(NativeBN, bn2litEndInts, "(J)[I"),
610    NATIVE_METHOD(NativeBN, getNativeFinalizer, "()J"),
611    NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZJ)V"),
612    NATIVE_METHOD(NativeBN, longInt, "(J)J"),
613    NATIVE_METHOD(NativeBN, putLongInt, "(JJ)V"),
614    NATIVE_METHOD(NativeBN, putULongInt, "(JJZ)V"),
615    NATIVE_METHOD(NativeBN, sign, "(J)I"),
616    NATIVE_METHOD(NativeBN, twosComp2bn, "([BIJ)V"),
617 };
register_java_math_NativeBN(JNIEnv * env)618 void register_java_math_NativeBN(JNIEnv* env) {
619     jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
620 }
621