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