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 #include <jni.h>
     22 #include <JNIHelp.h>
     23 #include <openssl/err.h>
     24 #include <openssl/crypto.h>
     25 #include <openssl/bn.h>
     26 #include <stdio.h>
     27 
     28 #define mcSignednessBull void *
     29 #ifndef FALSE
     30 #define FALSE 0
     31 #define TRUE 1
     32 #endif
     33 
     34 static int isValidHandle (JNIEnv* env, void* handle, const char *message) {
     35     if (handle == NULL) {
     36         jniThrowNullPointerException(env, message);
     37         return FALSE;
     38     }
     39     return TRUE;
     40 }
     41 
     42 static int oneValidHandle (JNIEnv* env, void* a)
     43 {
     44     return isValidHandle(env, a, "Mandatory handle (first) passed as null");
     45 }
     46 
     47 static int twoValidHandles (JNIEnv* env, void* a, void *b)
     48 {
     49     if (!oneValidHandle(env, a)) return FALSE;
     50     return isValidHandle(env, b, "Mandatory handle (second) passed as null");
     51 }
     52 
     53 static int threeValidHandles (JNIEnv* env, void* a, void *b, void* c)
     54 {
     55     if (!twoValidHandles(env, a, b)) return FALSE;
     56     return isValidHandle(env, c, "Mandatory handle (third) passed as null");
     57 }
     58 
     59 static int fourValidHandles (JNIEnv* env, void* a, void *b, void* c, void* d)
     60 {
     61     if (!threeValidHandles(env, a, b, c)) return FALSE;
     62     return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
     63 }
     64 
     65 
     66 /**
     67  * public static native int ERR_get_error();
     68  */
     69 static unsigned long NativeBN_ERR_get_error(JNIEnv* env, jclass cls) {
     70     unsigned long e = ERR_get_error();
     71     return e;
     72 }
     73 
     74 /**
     75  * public static native String ERR_error_string(int);
     76  */
     77 static jstring NativeBN_ERR_error_string(JNIEnv* env, jclass cls, unsigned long e) {
     78     jstring returnJString = 0;
     79     char* errStr;
     80     errStr = ERR_error_string(e, NULL);
     81     returnJString = ((*env)->NewStringUTF(env, (mcSignednessBull)errStr));
     82     return returnJString;
     83 }
     84 
     85 
     86 /**
     87  * public static native int BN_CTX_new()
     88  */
     89 static BN_CTX* NativeBN_BN_CTX_new(JNIEnv* env, jclass cls) {
     90     return BN_CTX_new();
     91 }
     92 
     93 
     94 /**
     95  * public static native int BN_new()
     96  */
     97 static BIGNUM* NativeBN_BN_new(JNIEnv* env, jclass cls) {
     98     return BN_new();
     99 }
    100 
    101 /**
    102  * public static native int BN_free()
    103  */
    104 static void NativeBN_BN_free(JNIEnv* env, jclass cls, BIGNUM* a) {
    105     if (!oneValidHandle(env, a)) return;
    106     BN_free(a);
    107 }
    108 
    109 
    110 /**
    111  * public static native int BN_cmp(int, int)
    112  */
    113 static int NativeBN_BN_cmp(JNIEnv* env, jclass cls, BIGNUM* a, BIGNUM* b) {
    114     if (!twoValidHandles(env, a, b)) return 1;
    115     return BN_cmp(a, b);
    116 }
    117 
    118 /**
    119  * public static native int BN_copy(int, int)
    120  */
    121 static jboolean NativeBN_BN_copy(JNIEnv* env, jclass cls, BIGNUM* to, BIGNUM* from) {
    122     if (!twoValidHandles(env, to, from)) return FALSE;
    123     return (BN_copy(to, from) != NULL);
    124 }
    125 
    126 
    127 /**
    128  * public static native int putULongInt(int, long, int)
    129  */
    130 static jboolean NativeBN_putULongInt(JNIEnv* env, jclass cls, BIGNUM* a, unsigned long long dw, jboolean neg) {
    131     if (!oneValidHandle(env, a)) return FALSE;
    132     unsigned int hi = dw >> 32; // This shifts without sign extension.
    133     int lo = (int)dw; // This truncates implicitely.
    134 
    135     // cf. litEndInts2bn:
    136     bn_check_top(a);
    137         if (bn_wexpand(a, 2) != NULL) {
    138             a->d[0] = lo;
    139             a->d[1] = hi;
    140             a->top = 2;
    141             a->neg = neg;
    142             bn_correct_top(a);
    143             return TRUE;
    144         }
    145         else return FALSE;
    146 }
    147 
    148 /**
    149  * public static native int putLongInt(int, long)
    150  */
    151 static jboolean NativeBN_putLongInt(JNIEnv* env, jclass cls, BIGNUM* a, long long dw) {
    152     if (dw >= 0) return NativeBN_putULongInt(env, cls, a, dw, FALSE);
    153     else return NativeBN_putULongInt(env, cls, a, -dw, TRUE);
    154 }
    155 
    156 /**
    157  * public static native int BN_dec2bn(int, java.lang.String)
    158  */
    159 static int NativeBN_BN_dec2bn(JNIEnv* env, jclass cls, BIGNUM* a, jstring str) {
    160     if (!oneValidHandle(env, a)) return -1;
    161     char* tmpStr = (char*)(*env)->GetStringUTFChars(env, str, NULL);
    162     if (tmpStr != NULL) {
    163         int len = BN_dec2bn(&a, tmpStr);
    164         (*env)->ReleaseStringUTFChars(env, str, tmpStr);
    165         return len; // len == 0: Error
    166     }
    167     else return -1; // Error outside BN.
    168 }
    169 
    170 /**
    171  * public static native int BN_hex2bn(int, java.lang.String)
    172  */
    173 static int NativeBN_BN_hex2bn(JNIEnv* env, jclass cls, BIGNUM* a, jstring str) {
    174    if (!oneValidHandle(env, a)) return -1;
    175     char* tmpStr = (char*)(*env)->GetStringUTFChars(env, str, NULL);
    176     if (tmpStr != NULL) {
    177         int len = BN_hex2bn(&a, tmpStr);
    178         (*env)->ReleaseStringUTFChars(env, str, tmpStr);
    179         return len; // len == 0: Error
    180     }
    181     else return -1; // Error outside BN.
    182 }
    183 
    184 /**
    185  * public static native boolean BN_bin2bn(byte[], int, int, int)
    186  */
    187 static jboolean NativeBN_BN_bin2bn(JNIEnv* env, jclass cls, jbyteArray arr, int len, jboolean neg, BIGNUM* ret) {
    188     if (!oneValidHandle(env, ret)) return FALSE;
    189     jboolean success;
    190     unsigned char * tmpBytes;
    191     tmpBytes = (unsigned char *)((*env)->GetPrimitiveArrayCritical(env, arr, 0));
    192     if (tmpBytes != NULL) {
    193         success = (BN_bin2bn(tmpBytes, len, ret) != NULL);
    194         if (neg) {
    195             BN_set_negative(ret, 1);
    196         }
    197         (*env)->ReleasePrimitiveArrayCritical(env, arr, tmpBytes, JNI_ABORT);
    198         return success;
    199     }
    200     else return -1; // Error outside BN. mc FIXME: what to do in this case? Does JNI throw exception itself?
    201 }
    202 
    203 /**
    204  * public static native boolean litEndInts2bn(int[], int, int, int)
    205  * Note:
    206  * This procedure directly writes the internal representation of BIGNUMs.
    207  * We do so as there is no direct interface based on Little Endian Integer Arrays.
    208  * Also note that the same representation is used in the Cordoba Java Implementation of BigIntegers,
    209  *        whereof certain functionality is still being used.
    210  */
    211 static jboolean NativeBN_litEndInts2bn(JNIEnv* env, jclass cls, jintArray arr, int len, jboolean neg, BIGNUM* ret) {
    212     if (!oneValidHandle(env, ret)) return FALSE;
    213     bn_check_top(ret);
    214 	if (len > 0) {
    215         BN_ULONG* tmpInts; // BN_ULONG is 4 Bytes on this system for sure, i.e. same as jint!
    216         tmpInts = (BN_ULONG*)((*env)->GetPrimitiveArrayCritical(env, arr, 0));
    217         if ((tmpInts != NULL) && (bn_wexpand(ret, len) != NULL)) {
    218             int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
    219             (*env)->ReleasePrimitiveArrayCritical(env, arr, tmpInts, JNI_ABORT);
    220             ret->top = len;
    221             ret->neg = neg;
    222             // need to call this due to clear byte at top if avoiding
    223             // having the top bit set (-ve number)
    224             // Basically get rid of top zero ints:
    225             bn_correct_top(ret);
    226             return TRUE;
    227         }
    228         else {
    229             if (tmpInts != NULL)
    230                 (*env)->ReleasePrimitiveArrayCritical(env, arr, tmpInts, JNI_ABORT);
    231             return FALSE;
    232         }
    233 	}
    234 	else { // (len = 0) means value = 0 and sign will be 0, too.
    235 		ret->top = 0;
    236     	return TRUE;
    237 	}
    238 }
    239 
    240 
    241 #define BYTES2INT(bytes, k) \
    242  (  (bytes[k + 3] & 0xFF) \
    243   | (bytes[k + 2] & 0xFF) << 8 \
    244   | (bytes[k + 1] & 0xFF) << 16 \
    245   | (bytes[k + 0] & 0xFF) << 24 )
    246 
    247 static jboolean negBigEndianBytes2bn(JNIEnv* env, jclass cls, unsigned char* bytes, int bytesLen, BIGNUM* ret) {
    248 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
    249 //
    250     bn_check_top(ret);
    251 // FIXME: ASSERT (bytesLen > 0);
    252 	int intLen = (bytesLen + 3) / 4;
    253 	int firstNonzeroDigit = -2;
    254     if (bn_wexpand(ret, intLen) != NULL) {
    255         BN_ULONG* d = ret->d;
    256         BN_ULONG di;
    257         ret->top = intLen;
    258         int highBytes = bytesLen % 4;
    259         int k = bytesLen;
    260         // Put bytes to the int array starting from the end of the byte array
    261         int i = 0;
    262         while (k > highBytes) {
    263             k -= 4;
    264             di = BYTES2INT(bytes, k);
    265             if (di != 0) {
    266                 d[i] = -di;
    267                 firstNonzeroDigit = i;
    268                 i++;
    269                 while (k > highBytes) {
    270                     k -= 4;
    271                     d[i] = ~BYTES2INT(bytes, k);
    272                     i++;
    273                 }
    274                 break;
    275             } else {
    276                 d[i] = 0;
    277                 i++;
    278             }
    279         }
    280         if (highBytes != 0) {
    281             di = -1;
    282             // Put the first bytes in the highest element of the int array
    283             if (firstNonzeroDigit != -2) {
    284                 for (k = 0; k < highBytes; k++) {
    285                     di = (di << 8) | (bytes[k] & 0xFF);
    286                 }
    287                 d[i] = ~di;
    288             } else {
    289                 for (k = 0; k < highBytes; k++) {
    290                     di = (di << 8) | (bytes[k] & 0xFF);
    291                 }
    292                 d[i] = -di;
    293             }
    294         }
    295         return TRUE;
    296     }
    297     else return FALSE;
    298 }
    299 
    300 /**
    301  * public static native boolean twosComp2bn(byte[], int, int)
    302  */
    303 static jboolean NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, BIGNUM* ret) {
    304     if (!oneValidHandle(env, ret)) return FALSE;
    305     jboolean success;
    306     unsigned char* tmpBytes;
    307     tmpBytes = (unsigned char*)((*env)->GetPrimitiveArrayCritical(env, arr, 0));
    308     if (tmpBytes != NULL) {
    309         if ((tmpBytes[0] & 0X80) == 0) { // Positive value!
    310             //
    311             // We can use the existing BN implementation for unsigned big endian bytes:
    312             //
    313             success = (BN_bin2bn(tmpBytes, bytesLen, ret) != NULL);
    314             BN_set_negative(ret, FALSE);
    315         }
    316         else { // Negative value!
    317             //
    318             // We need to apply two's complement:
    319             //
    320             success = negBigEndianBytes2bn(env, cls, tmpBytes, bytesLen, ret);
    321             BN_set_negative(ret, TRUE);
    322         }
    323         (*env)->ReleasePrimitiveArrayCritical(env, arr, tmpBytes, JNI_ABORT);
    324         return success;
    325     }
    326     else return -1; // Error outside BN. mc FIXME: what to do in this case? Does JNI throw exception itself?
    327 }
    328 
    329 
    330 /**
    331  * public static native long longInt(int)
    332  */
    333 static long long NativeBN_longInt(JNIEnv* env, jclass cls, BIGNUM* a) {
    334     if (!oneValidHandle(env, a)) return -1;
    335     bn_check_top(a);
    336     int intLen = a->top;
    337     BN_ULONG* d = a->d;
    338     switch (intLen) {
    339     case 0:
    340         return 0;
    341     case 1:
    342         if (!a->neg) return d[0] & 0X00000000FFFFFFFFLL;
    343         else return -(d[0] & 0X00000000FFFFFFFFLL);
    344     default:
    345         if (!a->neg) return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
    346         else return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
    347     }
    348 }
    349 
    350 
    351 static char* leadingZerosTrimmed(char* s) {
    352     char* p = s;
    353     if (*p == '-') {
    354         p++;
    355         while ((*p == '0') && (*(p + 1) != 0)) { p++; }
    356         p--;
    357         *p = '-';
    358     } else {
    359         while ((*p == '0') && (*(p + 1) != 0)) { p++; }
    360     }
    361     return p;
    362 }
    363 
    364 /**
    365  * public static native java.lang.String BN_bn2dec(int)
    366  */
    367 static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass cls, BIGNUM* a) {
    368     if (!oneValidHandle(env, a)) return NULL;
    369     char* tmpStr;
    370     char* retStr;
    371     tmpStr = BN_bn2dec(a);
    372     if (tmpStr != NULL) {
    373         retStr = leadingZerosTrimmed(tmpStr);
    374         jstring returnJString = ((*env)->NewStringUTF(env, (mcSignednessBull)retStr));
    375         OPENSSL_free(tmpStr);
    376         return returnJString;
    377     }
    378     else return NULL;
    379 }
    380 
    381 /**
    382  * public static native java.lang.String BN_bn2hex(int)
    383  */
    384 static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass cls, BIGNUM* a) {
    385     if (!oneValidHandle(env, a)) return NULL;
    386     char* tmpStr;
    387     char* retStr;
    388     tmpStr = BN_bn2hex(a);
    389     if (tmpStr != NULL) {
    390         retStr = leadingZerosTrimmed(tmpStr);
    391         jstring returnJString = ((*env)->NewStringUTF(env, (mcSignednessBull)retStr));
    392         OPENSSL_free(tmpStr);
    393         return returnJString;
    394     }
    395     else return NULL;
    396 }
    397 
    398 /**
    399  * public static native byte[] BN_bn2bin(int, byte[])
    400  */
    401 static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass cls, BIGNUM* a, jbyteArray to) {
    402     if (!oneValidHandle(env, a)) return NULL;
    403     jbyteArray returnJBytes = to;
    404     unsigned char * tmpBytes;
    405     int len, byteCnt;
    406     byteCnt = BN_num_bytes(a);
    407 // FIXME: Currently ignoring array passed in to:
    408     returnJBytes = (*env)->NewByteArray(env, byteCnt);
    409 // FIXME: is it neccessary to check for returnJBytes != NULL?
    410     tmpBytes = (unsigned char *)((*env)->GetPrimitiveArrayCritical(env, returnJBytes, NULL));
    411     if (tmpBytes != NULL) {
    412         len = BN_bn2bin(a, tmpBytes);
    413         (*env)->ReleasePrimitiveArrayCritical(env, returnJBytes, tmpBytes, 0);
    414         return returnJBytes;
    415     }
    416     else return NULL;
    417 }
    418 
    419 /**
    420  * public static native int[] bn2litEndInts(int, int[])
    421  * cf. litEndInts2bn
    422  */
    423 static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass cls, BIGNUM* a, jintArray to) {
    424     if (!oneValidHandle(env, a)) return NULL;
    425     jintArray returnJInts = to;
    426     bn_check_top(a);
    427     int len = a->top;
    428     if (len > 0) {
    429 // FIXME: Currently ignoring array passed in to:
    430         returnJInts = (*env)->NewIntArray(env, len);
    431 // FIXME: is it neccessary to check for returnJBytes != NULL?
    432         BN_ULONG* tmpInts = (BN_ULONG*)((*env)->GetPrimitiveArrayCritical(env, returnJInts, NULL));
    433         if (tmpInts != NULL) {
    434             int i = len; do { i--; tmpInts[i] = a->d[i]; } while (i > 0);
    435             (*env)->ReleasePrimitiveArrayCritical(env, returnJInts, tmpInts, 0);
    436             return returnJInts;
    437         }
    438         else return NULL;
    439     }
    440     else { // value = 0
    441         return NULL; // Client should not call when sign = 0!
    442     }
    443 }
    444 
    445 
    446 /**
    447  * public static native int sign(int)
    448  */
    449 static int NativeBN_sign(JNIEnv* env, jclass cls, BIGNUM* a) {
    450     if (!oneValidHandle(env, a)) return -2;
    451     if (BN_is_zero(a)) return 0;
    452     else if (BN_is_negative(a)) return -1;
    453     else return 1;
    454 }
    455 
    456 /**
    457  * public static native void BN_set_negative(int, int)
    458  */
    459 static void NativeBN_BN_set_negative(JNIEnv* env, jclass cls, BIGNUM* b, int n) {
    460     if (!oneValidHandle(env, b)) return;
    461     BN_set_negative(b, n);
    462 }
    463 
    464 /**
    465  * public static native int bitLength(int)
    466  */
    467 static int NativeBN_bitLength(JNIEnv* env, jclass cls, BIGNUM* a) {
    468 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
    469 //
    470     if (!oneValidHandle(env, a)) return FALSE;
    471     bn_check_top(a);
    472     int intLen = a->top;
    473     if (intLen == 0) return 0;
    474     BN_ULONG* d = a->d;
    475     int i = intLen - 1;
    476     BN_ULONG msd = d[i]; // most significant digit
    477         if (a->neg) {
    478             // Handle negative values correctly:
    479             // i.e. decrement the msd if all other digits are 0:
    480             // while ((i > 0) && (d[i] != 0)) { i--; }
    481             do { i--; } while (!((i < 0) || (d[i] != 0)));
    482             if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
    483         }
    484         return (intLen - 1) * 32 + BN_num_bits_word(msd);
    485 }
    486 
    487 /**
    488  * public static native boolean BN_is_bit_set(int, int)
    489  */
    490 static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass cls, BIGNUM* a, int n) {
    491     if (!oneValidHandle(env, a)) return FALSE;
    492     return (jboolean)BN_is_bit_set(a, n);
    493 }
    494 
    495 /**
    496  * public static native void modifyBit(int, int, int)
    497  */
    498 static jboolean NativeBN_modifyBit(JNIEnv* env, jclass cls, BIGNUM* a, int n, int op) {
    499 // LOGD("NativeBN_BN_modifyBit");
    500     if (!oneValidHandle(env, a)) return FALSE;
    501     switch (op) {
    502     case 1: return BN_set_bit(a, n);
    503     case 0: return BN_clear_bit(a, n);
    504     case -1:
    505         if (BN_is_bit_set(a, n)) return BN_clear_bit(a, n);
    506         else return BN_set_bit(a, n);
    507     }
    508     return FALSE;
    509 }
    510 
    511 /**
    512  * public static native int BN_lshift(int, int, int)
    513  */
    514 static jboolean NativeBN_BN_lshift(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, int n) {
    515 // LOGD("NativeBN_BN_lshift %p %p %d", r, a, n);
    516     if (!twoValidHandles(env, r, a)) return FALSE;
    517     if (n >= 0) return BN_lshift(r, a, n);
    518 
    519     n = -n;
    520 //    return BN_rshift(r, a, n);
    521 // Following code insourced from bn_shift.c in order to have bug fixed:
    522 // FIXME: Should report to openssl team!!!
    523 
    524 	int i,j,nw,lb,rb;
    525 	BN_ULONG *t,*f;
    526 	BN_ULONG l,tmp;
    527 
    528 	bn_check_top(r);
    529 	bn_check_top(a);
    530 
    531 	nw=n/BN_BITS2;
    532 	rb=n%BN_BITS2;
    533 	lb=BN_BITS2-rb;
    534 // Changed "nw > a->top || a->top == 0" to nw >= a->top" as considering this a bug:
    535 	if (nw >= a->top)
    536 		{
    537 		BN_zero(r);
    538 		return(1);
    539 		}
    540 	if (r != a)
    541 		{
    542 		r->neg=a->neg;
    543 		if (bn_wexpand(r,a->top-nw+1) == NULL) return(0);
    544 		}
    545 	else
    546 		{
    547 		if (n == 0)
    548 			return 1; /* or the copying loop will go berserk */
    549 		}
    550 
    551 	f= &(a->d[nw]);
    552 	t=r->d;
    553 	j=a->top-nw;
    554 	r->top=j;
    555 
    556 	if (rb == 0)
    557 		{
    558 		for (i=j; i != 0; i--)
    559 			*(t++)= *(f++);
    560 		}
    561 	else
    562 		{
    563 		l= *(f++);
    564 		for (i=j-1; i != 0; i--)
    565 			{
    566 			tmp =(l>>rb)&BN_MASK2;
    567 			l= *(f++);
    568 			*(t++) =(tmp|(l<<lb))&BN_MASK2;
    569 			}
    570 		*(t++) =(l>>rb)&BN_MASK2;
    571 		}
    572 	bn_correct_top(r);
    573 	bn_check_top(r);
    574 	return(1);
    575 }
    576 
    577 
    578 /**
    579  * public static native boolean BN_add_word(int, int)
    580  */
    581 static jboolean NativeBN_BN_add_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
    582     if (!oneValidHandle(env, a)) return FALSE;
    583     return BN_add_word(a, w);
    584 }
    585 
    586 /**
    587  * public static native boolean BN_sub_word(int, int)
    588  */
    589 static jboolean NativeBN_BN_sub_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
    590     if (!oneValidHandle(env, a)) return FALSE;
    591     return BN_sub_word(a, w);
    592 }
    593 
    594 /**
    595  * public static native boolean BN_mul_word(int, int)
    596  */
    597 static jboolean NativeBN_BN_mul_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
    598     if (!oneValidHandle(env, a)) return FALSE;
    599     return BN_mul_word(a, w);
    600 }
    601 
    602 /**
    603  * public static native boolean BN_div_word(int, int)
    604  */
    605 static BN_ULONG NativeBN_BN_div_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
    606     if (!oneValidHandle(env, a)) return FALSE;
    607     return BN_div_word(a, w);
    608 }
    609 
    610 /**
    611  * public static native boolean BN_mod_word(int, int)
    612  */
    613 static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
    614     if (!oneValidHandle(env, a)) return FALSE;
    615     return BN_mod_word(a, w);
    616 }
    617 
    618 
    619 
    620 /**
    621  * public static native int BN_add(int, int, int)
    622  */
    623 static jboolean NativeBN_BN_add(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
    624     if (!threeValidHandles(env, r, a, b)) return FALSE;
    625     return BN_add(r, a, b);
    626 }
    627 
    628 /**
    629  * public static native int BN_sub(int, int, int)
    630  */
    631 static jboolean NativeBN_BN_sub(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
    632     if (!threeValidHandles(env, r, a, b)) return FALSE;
    633     return BN_sub(r, a, b);
    634 }
    635 
    636 
    637 /**
    638  * public static native int BN_gcd(int, int, int, int)
    639  */
    640 static jboolean NativeBN_BN_gcd(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* b, BN_CTX* ctx) {
    641     if (!threeValidHandles(env, r, a, b)) return FALSE;
    642     return BN_gcd(r, a, b, ctx);
    643 }
    644 
    645 /**
    646  * public static native int BN_mul(int, int, int, int)
    647  */
    648 static jboolean NativeBN_BN_mul(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* b, BN_CTX* ctx) {
    649     if (!threeValidHandles(env, r, a, b)) return FALSE;
    650     return BN_mul(r, a, b, ctx);
    651 }
    652 
    653 /**
    654  * public static native int BN_exp(int, int, int, int)
    655  */
    656 static jboolean NativeBN_BN_exp(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* p, BN_CTX* ctx) {
    657     if (!threeValidHandles(env, r, a, p)) return FALSE;
    658     return BN_exp(r, a, p, ctx);
    659 }
    660 
    661 /**
    662  * public static native boolean BN_div(int, int, int, int, int)
    663  */
    664 static jboolean NativeBN_BN_div(JNIEnv* env, jclass cls, BIGNUM* dv, BIGNUM* rem, BIGNUM* m, BIGNUM* d, BN_CTX* ctx) {
    665     if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return FALSE;
    666     return BN_div(dv, rem, m, d, ctx);
    667 }
    668 
    669 /**
    670  * public static native int BN_nnmod(int, int, int, int)
    671  */
    672 static jboolean NativeBN_BN_nnmod(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* m, BN_CTX* ctx) {
    673     if (!threeValidHandles(env, r, a, m)) return FALSE;
    674     return BN_nnmod(r, a, m, ctx);
    675 }
    676 
    677 /**
    678  * public static native int BN_mod_exp(int, int, int, int, int)
    679  */
    680 static jboolean NativeBN_BN_mod_exp(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* p, BIGNUM* m, BN_CTX* ctx) {
    681     if (!fourValidHandles(env, r, a, p, m)) return FALSE;
    682     return BN_mod_exp(r, a, p, m, ctx);
    683 }
    684 
    685 
    686 /**
    687  * public static native int BN_mod_inverse(int, int, int, int)
    688  */
    689 static jboolean NativeBN_BN_mod_inverse(JNIEnv* env, jclass cls, BIGNUM* ret, BIGNUM* a, BIGNUM* n, BN_CTX* ctx) {
    690     if (!threeValidHandles(env, ret, a, n)) return FALSE;
    691     return (BN_mod_inverse(ret, a, n, ctx) != NULL);
    692 }
    693 
    694 
    695 /**
    696  * public static native int BN_generate_prime_ex(int, int, boolean, int, int, int)
    697  */
    698 static jboolean NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass cls, BIGNUM* ret, int bits, jboolean safe,
    699         BIGNUM* add, BIGNUM* rem, jint cb) {
    700     if (!oneValidHandle(env, ret)) return FALSE;
    701     return BN_generate_prime_ex(ret, bits, safe, add, rem, cb);
    702 }
    703 
    704 /**
    705  * public static native int BN_mod_inverse(int, int, int, int)
    706  */
    707 static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass cls, BIGNUM* p, int nchecks, BN_CTX* ctx, jint cb) {
    708     if (!oneValidHandle(env, p)) return FALSE;
    709     return BN_is_prime_ex(p, nchecks, ctx, cb);
    710 }
    711 
    712 
    713 /**
    714  * Defines the mapping from Java methods and their signatures
    715  * to native functions. Order is Java name, Java signature,
    716  * then pointer to C function.
    717  */
    718 static JNINativeMethod METHODS[] = {
    719    { "ERR_get_error", "()I", (void*)NativeBN_ERR_get_error },
    720    { "ERR_error_string", "(I)Ljava/lang/String;", (void*)NativeBN_ERR_error_string },
    721    { "BN_CTX_new", "()I", (void*)NativeBN_BN_CTX_new },
    722    { "BN_new", "()I", (void*)NativeBN_BN_new },
    723    { "BN_free", "(I)V", (void*)NativeBN_BN_free },
    724    { "BN_cmp", "(II)I", (void*)NativeBN_BN_cmp },
    725    { "BN_copy", "(II)Z", (void*)NativeBN_BN_copy },
    726    { "putLongInt", "(IJ)Z", (void*)NativeBN_putLongInt },
    727    { "putULongInt", "(IJZ)Z", (void*)NativeBN_putULongInt },
    728    { "BN_dec2bn", "(ILjava/lang/String;)I", (void*)NativeBN_BN_dec2bn },
    729    { "BN_hex2bn", "(ILjava/lang/String;)I", (void*)NativeBN_BN_hex2bn },
    730    { "BN_bin2bn", "([BIZI)Z", (void*)NativeBN_BN_bin2bn },
    731    { "litEndInts2bn", "([IIZI)Z", (void*)NativeBN_litEndInts2bn },
    732    { "twosComp2bn", "([BII)Z", (void*)NativeBN_twosComp2bn },
    733    { "longInt", "(I)J", (void*)NativeBN_longInt },
    734    { "BN_bn2dec", "(I)Ljava/lang/String;", (void*)NativeBN_BN_bn2dec },
    735    { "BN_bn2hex", "(I)Ljava/lang/String;", (void*)NativeBN_BN_bn2hex },
    736    { "BN_bn2bin", "(I[B)[B", (void*)NativeBN_BN_bn2bin },
    737    { "bn2litEndInts", "(I[I)[I", (void*)NativeBN_bn2litEndInts },
    738    { "sign", "(I)I", (void*)NativeBN_sign },
    739    { "BN_set_negative", "(II)V", (void*)NativeBN_BN_set_negative },
    740    { "bitLength", "(I)I", (void*)NativeBN_bitLength },
    741    { "BN_is_bit_set", "(II)Z", (void*)NativeBN_BN_is_bit_set },
    742    { "modifyBit", "(III)Z", (void*)NativeBN_modifyBit },
    743    { "BN_lshift", "(III)Z", (void*)NativeBN_BN_lshift },
    744    { "BN_add_word", "(II)Z", (void*)NativeBN_BN_add_word },
    745    { "BN_sub_word", "(II)Z", (void*)NativeBN_BN_sub_word },
    746    { "BN_mul_word", "(II)Z", (void*)NativeBN_BN_mul_word },
    747    { "BN_div_word", "(II)I", (void*)NativeBN_BN_div_word },
    748    { "BN_mod_word", "(II)I", (void*)NativeBN_BN_mod_word },
    749    { "BN_add", "(III)Z", (void*)NativeBN_BN_add },
    750    { "BN_sub", "(III)Z", (void*)NativeBN_BN_sub },
    751    { "BN_gcd", "(IIII)Z", (void*)NativeBN_BN_gcd },
    752    { "BN_mul", "(IIII)Z", (void*)NativeBN_BN_mul },
    753    { "BN_exp", "(IIII)Z", (void*)NativeBN_BN_exp },
    754    { "BN_div", "(IIIII)Z", (void*)NativeBN_BN_div },
    755    { "BN_nnmod", "(IIII)Z", (void*)NativeBN_BN_nnmod },
    756    { "BN_mod_exp", "(IIIII)Z", (void*)NativeBN_BN_mod_exp },
    757    { "BN_mod_inverse", "(IIII)Z", (void*)NativeBN_BN_mod_inverse },
    758    { "BN_generate_prime_ex", "(IIZIII)Z", (void*)NativeBN_BN_generate_prime_ex },
    759    { "BN_is_prime_ex", "(IIII)Z", (void*)NativeBN_BN_is_prime_ex }
    760 };
    761 
    762 int register_org_openssl_NativeBN(JNIEnv* env) {
    763    return jniRegisterNativeMethods(env, "org/openssl/NativeBN", METHODS, NELEM(METHODS));
    764 }
    765