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