Home | History | Annotate | Download | only in native
      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|. */
     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 {
     44   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 
     50 static BIGNUM* toBigNum(jlong address) {
     51   return reinterpret_cast<BIGNUM*>(static_cast<uintptr_t>(address));
     52 }
     53 
     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 
     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 
     82 static int oneValidHandle(JNIEnv* env, jlong a) {
     83   return isValidHandle(env, a, "Mandatory handle (first) passed as null");
     84 }
     85 
     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 
     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 
     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 
    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 
    107 static jlong NativeBN_getNativeFinalizer(JNIEnv*, jclass) {
    108   return static_cast<jlong>(reinterpret_cast<uintptr_t>(&BN_free));
    109 }
    110 
    111 static void NativeBN_BN_free(JNIEnv* env, jclass, jlong a) {
    112   if (!oneValidHandle(env, a)) return;
    113   BN_free(toBigNum(a));
    114 }
    115 
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 };
    618 void register_java_math_NativeBN(JNIEnv* env) {
    619     jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
    620 }
    621