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