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