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