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