• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "UniquePtr.h"
28 #include "jni.h"
29 #include <assert.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 {
operator ()BN_CTX_Deleter36     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 
isValidHandle(JNIEnv * env,void * handle,const char * message)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 
oneValidHandle(JNIEnv * env,void * a)50 static int oneValidHandle (JNIEnv* env, void* a)
51 {
52     return isValidHandle(env, a, "Mandatory handle (first) passed as null");
53 }
54 
twoValidHandles(JNIEnv * env,void * a,void * b)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 
threeValidHandles(JNIEnv * env,void * a,void * b,void * c)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 
fourValidHandles(JNIEnv * env,void * a,void * b,void * c,void * d)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 
NativeBN_ERR_get_error(JNIEnv *,jclass)73 static unsigned long NativeBN_ERR_get_error(JNIEnv*, jclass) {
74     return ERR_get_error();
75 }
76 
NativeBN_ERR_error_string(JNIEnv * env,jclass,unsigned long e)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 
NativeBN_BN_new(JNIEnv *,jclass)82 static BIGNUM* NativeBN_BN_new(JNIEnv*, jclass) {
83     return BN_new();
84 }
85 
NativeBN_BN_free(JNIEnv * env,jclass,BIGNUM * a)86 static void NativeBN_BN_free(JNIEnv* env, jclass, BIGNUM* a) {
87     if (!oneValidHandle(env, a)) return;
88     BN_free(a);
89 }
90 
NativeBN_BN_cmp(JNIEnv * env,jclass,BIGNUM * a,BIGNUM * b)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 
NativeBN_BN_copy(JNIEnv * env,jclass,BIGNUM * to,BIGNUM * from)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 
NativeBN_putULongInt(JNIEnv * env,jclass,BIGNUM * a,unsigned long long dw,jboolean neg)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 
NativeBN_putLongInt(JNIEnv * env,jclass cls,BIGNUM * a,long long dw)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 
NativeBN_BN_dec2bn(JNIEnv * env,jclass,BIGNUM * a,jstring str)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 
NativeBN_BN_hex2bn(JNIEnv * env,jclass,BIGNUM * a,jstring str)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 
NativeBN_BN_bin2bn(JNIEnv * env,jclass,jbyteArray arr,int len,jboolean neg,BIGNUM * ret)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  */
NativeBN_litEndInts2bn(JNIEnv * env,jclass,jintArray arr,int len,jboolean neg,BIGNUM * ret)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         assert(sizeof(BN_ULONG) == sizeof(jint));
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 
negBigEndianBytes2bn(JNIEnv *,jclass,const unsigned char * bytes,int bytesLen,BIGNUM * ret)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 //
202     bn_check_top(ret);
203 // FIXME: ASSERT (bytesLen > 0);
204     int intLen = (bytesLen + 3) / 4;
205     int firstNonzeroDigit = -2;
206     if (bn_wexpand(ret, intLen) != NULL) {
207         BN_ULONG* d = ret->d;
208         BN_ULONG di;
209         ret->top = intLen;
210         int highBytes = bytesLen % 4;
211         int k = bytesLen;
212         // Put bytes to the int array starting from the end of the byte array
213         int i = 0;
214         while (k > highBytes) {
215             k -= 4;
216             di = BYTES2INT(bytes, k);
217             if (di != 0) {
218                 d[i] = -di;
219                 firstNonzeroDigit = i;
220                 i++;
221                 while (k > highBytes) {
222                     k -= 4;
223                     d[i] = ~BYTES2INT(bytes, k);
224                     i++;
225                 }
226                 break;
227             } else {
228                 d[i] = 0;
229                 i++;
230             }
231         }
232         if (highBytes != 0) {
233             di = -1;
234             // Put the first bytes in the highest element of the int array
235             if (firstNonzeroDigit != -2) {
236                 for (k = 0; k < highBytes; k++) {
237                     di = (di << 8) | (bytes[k] & 0xFF);
238                 }
239                 d[i] = ~di;
240             } else {
241                 for (k = 0; k < highBytes; k++) {
242                     di = (di << 8) | (bytes[k] & 0xFF);
243                 }
244                 d[i] = -di;
245             }
246         }
247         return JNI_TRUE;
248     }
249     else return JNI_FALSE;
250 }
251 
NativeBN_twosComp2bn(JNIEnv * env,jclass cls,jbyteArray arr,int bytesLen,BIGNUM * ret)252 static jboolean NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, BIGNUM* ret) {
253     if (!oneValidHandle(env, ret)) return JNI_FALSE;
254     ScopedByteArrayRO bytes(env, arr);
255     if (bytes.get() == NULL) {
256         return -1;
257     }
258     jboolean success;
259     const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
260     if ((bytes[0] & 0X80) == 0) { // Positive value!
261         //
262         // We can use the existing BN implementation for unsigned big endian bytes:
263         //
264         success = (BN_bin2bn(s, bytesLen, ret) != NULL);
265         BN_set_negative(ret, JNI_FALSE);
266     } else { // Negative value!
267         //
268         // We need to apply two's complement:
269         //
270         success = negBigEndianBytes2bn(env, cls, s, bytesLen, ret);
271         BN_set_negative(ret, JNI_TRUE);
272     }
273     return success;
274 }
275 
NativeBN_longInt(JNIEnv * env,jclass,BIGNUM * a)276 static long long NativeBN_longInt(JNIEnv* env, jclass, BIGNUM* a) {
277     if (!oneValidHandle(env, a)) return -1;
278     bn_check_top(a);
279     int intLen = a->top;
280     BN_ULONG* d = a->d;
281     switch (intLen) {
282     case 0:
283         return 0;
284     case 1:
285         if (!a->neg) return d[0] & 0X00000000FFFFFFFFLL;
286         else return -(d[0] & 0X00000000FFFFFFFFLL);
287     default:
288         if (!a->neg) return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
289         else return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
290     }
291 }
292 
leadingZerosTrimmed(char * s)293 static char* leadingZerosTrimmed(char* s) {
294     char* p = s;
295     if (*p == '-') {
296         p++;
297         while ((*p == '0') && (*(p + 1) != 0)) { p++; }
298         p--;
299         *p = '-';
300     } else {
301         while ((*p == '0') && (*(p + 1) != 0)) { p++; }
302     }
303     return p;
304 }
305 
NativeBN_BN_bn2dec(JNIEnv * env,jclass,BIGNUM * a)306 static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, BIGNUM* a) {
307     if (!oneValidHandle(env, a)) return NULL;
308     char* tmpStr;
309     char* retStr;
310     tmpStr = BN_bn2dec(a);
311     if (tmpStr != NULL) {
312         retStr = leadingZerosTrimmed(tmpStr);
313         jstring returnJString = env->NewStringUTF(retStr);
314         OPENSSL_free(tmpStr);
315         return returnJString;
316     }
317     else return NULL;
318 }
319 
NativeBN_BN_bn2hex(JNIEnv * env,jclass,BIGNUM * a)320 static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, BIGNUM* a) {
321     if (!oneValidHandle(env, a)) return NULL;
322     char* tmpStr;
323     char* retStr;
324     tmpStr = BN_bn2hex(a);
325     if (tmpStr != NULL) {
326         retStr = leadingZerosTrimmed(tmpStr);
327         jstring returnJString = env->NewStringUTF(retStr);
328         OPENSSL_free(tmpStr);
329         return returnJString;
330     }
331     else return NULL;
332 }
333 
NativeBN_BN_bn2bin(JNIEnv * env,jclass,BIGNUM * a)334 static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, BIGNUM* a) {
335     if (!oneValidHandle(env, a)) return NULL;
336     jbyteArray result = env->NewByteArray(BN_num_bytes(a));
337     if (result == NULL) {
338         return NULL;
339     }
340     ScopedByteArrayRW bytes(env, result);
341     if (bytes.get() == NULL) {
342         return NULL;
343     }
344     BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
345     return result;
346 }
347 
NativeBN_bn2litEndInts(JNIEnv * env,jclass,BIGNUM * a)348 static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, BIGNUM* a) {
349     if (!oneValidHandle(env, a)) return NULL;
350     bn_check_top(a);
351     int len = a->top;
352     if (len == 0) {
353         return NULL;
354     }
355     jintArray result = env->NewIntArray(len);
356     if (result == NULL) {
357         return NULL;
358     }
359     ScopedIntArrayRW ints(env, result);
360     if (ints.get() == NULL) {
361         return NULL;
362     }
363     BN_ULONG* ulongs = reinterpret_cast<BN_ULONG*>(ints.get());
364     if (ulongs == NULL) {
365         return NULL;
366     }
367     int i = len; do { i--; ulongs[i] = a->d[i]; } while (i > 0);
368     return result;
369 }
370 
NativeBN_sign(JNIEnv * env,jclass,BIGNUM * a)371 static int NativeBN_sign(JNIEnv* env, jclass, BIGNUM* a) {
372     if (!oneValidHandle(env, a)) return -2;
373     if (BN_is_zero(a)) return 0;
374     else if (BN_is_negative(a)) return -1;
375     else return 1;
376 }
377 
NativeBN_BN_set_negative(JNIEnv * env,jclass,BIGNUM * b,int n)378 static void NativeBN_BN_set_negative(JNIEnv* env, jclass, BIGNUM* b, int n) {
379     if (!oneValidHandle(env, b)) return;
380     BN_set_negative(b, n);
381 }
382 
NativeBN_bitLength(JNIEnv * env,jclass,BIGNUM * a)383 static int NativeBN_bitLength(JNIEnv* env, jclass, BIGNUM* a) {
384 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
385 //
386     if (!oneValidHandle(env, a)) return JNI_FALSE;
387     bn_check_top(a);
388     int intLen = a->top;
389     if (intLen == 0) return 0;
390     BN_ULONG* d = a->d;
391     int i = intLen - 1;
392     BN_ULONG msd = d[i]; // most significant digit
393         if (a->neg) {
394             // Handle negative values correctly:
395             // i.e. decrement the msd if all other digits are 0:
396             // while ((i > 0) && (d[i] != 0)) { i--; }
397             do { i--; } while (!((i < 0) || (d[i] != 0)));
398             if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
399         }
400         return (intLen - 1) * 32 + BN_num_bits_word(msd);
401 }
402 
NativeBN_BN_is_bit_set(JNIEnv * env,jclass,BIGNUM * a,int n)403 static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, BIGNUM* a, int n) {
404     if (!oneValidHandle(env, a)) return JNI_FALSE;
405     return (jboolean)BN_is_bit_set(a, n);
406 }
407 
NativeBN_modifyBit(JNIEnv * env,jclass,BIGNUM * a,int n,int op)408 static jboolean NativeBN_modifyBit(JNIEnv* env, jclass, BIGNUM* a, int n, int op) {
409 // LOGD("NativeBN_BN_modifyBit");
410     if (!oneValidHandle(env, a)) return JNI_FALSE;
411     switch (op) {
412     case 1: return BN_set_bit(a, n);
413     case 0: return BN_clear_bit(a, n);
414     case -1:
415         if (BN_is_bit_set(a, n)) return BN_clear_bit(a, n);
416         else return BN_set_bit(a, n);
417     }
418     return JNI_FALSE;
419 }
420 
NativeBN_BN_shift(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,int n)421 static jboolean NativeBN_BN_shift(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, int n) {
422     if (!twoValidHandles(env, r, a)) return JNI_FALSE;
423     return (n >= 0) ? BN_lshift(r, a, n) : BN_rshift(r, a, -n);
424 }
425 
NativeBN_BN_add_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)426 static jboolean NativeBN_BN_add_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
427     if (!oneValidHandle(env, a)) return JNI_FALSE;
428     return BN_add_word(a, w);
429 }
430 
NativeBN_BN_sub_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)431 static jboolean NativeBN_BN_sub_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
432     if (!oneValidHandle(env, a)) return JNI_FALSE;
433     return BN_sub_word(a, w);
434 }
435 
NativeBN_BN_mul_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)436 static jboolean NativeBN_BN_mul_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
437     if (!oneValidHandle(env, a)) return JNI_FALSE;
438     return BN_mul_word(a, w);
439 }
440 
NativeBN_BN_div_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)441 static BN_ULONG NativeBN_BN_div_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
442     if (!oneValidHandle(env, a)) return JNI_FALSE;
443     return BN_div_word(a, w);
444 }
445 
NativeBN_BN_mod_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)446 static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
447     if (!oneValidHandle(env, a)) return JNI_FALSE;
448     return BN_mod_word(a, w);
449 }
450 
NativeBN_BN_add(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)451 static jboolean NativeBN_BN_add(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
452     if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
453     return BN_add(r, a, b);
454 }
455 
NativeBN_BN_sub(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)456 static jboolean NativeBN_BN_sub(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
457     if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
458     return BN_sub(r, a, b);
459 }
460 
NativeBN_BN_gcd(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)461 static jboolean NativeBN_BN_gcd(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
462     if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
463     Unique_BN_CTX ctx(BN_CTX_new());
464     return BN_gcd(r, a, b, ctx.get());
465 }
466 
NativeBN_BN_mul(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)467 static jboolean NativeBN_BN_mul(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
468     if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
469     Unique_BN_CTX ctx(BN_CTX_new());
470     return BN_mul(r, a, b, ctx.get());
471 }
472 
NativeBN_BN_exp(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * p)473 static jboolean NativeBN_BN_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p) {
474     if (!threeValidHandles(env, r, a, p)) return JNI_FALSE;
475     Unique_BN_CTX ctx(BN_CTX_new());
476     return BN_exp(r, a, p, ctx.get());
477 }
478 
NativeBN_BN_div(JNIEnv * env,jclass,BIGNUM * dv,BIGNUM * rem,BIGNUM * m,BIGNUM * d)479 static jboolean NativeBN_BN_div(JNIEnv* env, jclass, BIGNUM* dv, BIGNUM* rem, BIGNUM* m, BIGNUM* d) {
480     if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return JNI_FALSE;
481     Unique_BN_CTX ctx(BN_CTX_new());
482     return BN_div(dv, rem, m, d, ctx.get());
483 }
484 
NativeBN_BN_nnmod(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * m)485 static jboolean NativeBN_BN_nnmod(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* m) {
486     if (!threeValidHandles(env, r, a, m)) return JNI_FALSE;
487     Unique_BN_CTX ctx(BN_CTX_new());
488     return BN_nnmod(r, a, m, ctx.get());
489 }
490 
NativeBN_BN_mod_exp(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * p,BIGNUM * m)491 static jboolean NativeBN_BN_mod_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p, BIGNUM* m) {
492     if (!fourValidHandles(env, r, a, p, m)) return JNI_FALSE;
493     Unique_BN_CTX ctx(BN_CTX_new());
494     return BN_mod_exp(r, a, p, m, ctx.get());
495 }
496 
NativeBN_BN_mod_inverse(JNIEnv * env,jclass,BIGNUM * ret,BIGNUM * a,BIGNUM * n)497 static jboolean NativeBN_BN_mod_inverse(JNIEnv* env, jclass, BIGNUM* ret, BIGNUM* a, BIGNUM* n) {
498     if (!threeValidHandles(env, ret, a, n)) return JNI_FALSE;
499     Unique_BN_CTX ctx(BN_CTX_new());
500     return (BN_mod_inverse(ret, a, n, ctx.get()) != NULL);
501 }
502 
NativeBN_BN_generate_prime_ex(JNIEnv * env,jclass,BIGNUM * ret,int bits,jboolean safe,BIGNUM * add,BIGNUM * rem,jint cb)503 static jboolean NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, BIGNUM* ret, int bits, jboolean safe,
504         BIGNUM* add, BIGNUM* rem, jint cb) {
505     if (!oneValidHandle(env, ret)) return JNI_FALSE;
506     return BN_generate_prime_ex(ret, bits, safe, add, rem, reinterpret_cast<BN_GENCB*>(cb));
507 }
508 
NativeBN_BN_is_prime_ex(JNIEnv * env,jclass,BIGNUM * p,int nchecks,jint cb)509 static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, BIGNUM* p, int nchecks, jint cb) {
510     if (!oneValidHandle(env, p)) return JNI_FALSE;
511     Unique_BN_CTX ctx(BN_CTX_new());
512     return BN_is_prime_ex(p, nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
513 }
514 
515 static JNINativeMethod gMethods[] = {
516    NATIVE_METHOD(NativeBN, BN_add, "(III)Z"),
517    NATIVE_METHOD(NativeBN, BN_add_word, "(II)Z"),
518    NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZI)Z"),
519    NATIVE_METHOD(NativeBN, BN_bn2bin, "(I)[B"),
520    NATIVE_METHOD(NativeBN, BN_bn2dec, "(I)Ljava/lang/String;"),
521    NATIVE_METHOD(NativeBN, BN_bn2hex, "(I)Ljava/lang/String;"),
522    NATIVE_METHOD(NativeBN, BN_cmp, "(II)I"),
523    NATIVE_METHOD(NativeBN, BN_copy, "(II)Z"),
524    NATIVE_METHOD(NativeBN, BN_dec2bn, "(ILjava/lang/String;)I"),
525    NATIVE_METHOD(NativeBN, BN_div, "(IIII)Z"),
526    NATIVE_METHOD(NativeBN, BN_div_word, "(II)I"),
527    NATIVE_METHOD(NativeBN, BN_exp, "(III)Z"),
528    NATIVE_METHOD(NativeBN, BN_free, "(I)V"),
529    NATIVE_METHOD(NativeBN, BN_gcd, "(III)Z"),
530    NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(IIZIII)Z"),
531    NATIVE_METHOD(NativeBN, BN_hex2bn, "(ILjava/lang/String;)I"),
532    NATIVE_METHOD(NativeBN, BN_is_bit_set, "(II)Z"),
533    NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(III)Z"),
534    NATIVE_METHOD(NativeBN, BN_mod_exp, "(IIII)Z"),
535    NATIVE_METHOD(NativeBN, BN_mod_inverse, "(III)Z"),
536    NATIVE_METHOD(NativeBN, BN_mod_word, "(II)I"),
537    NATIVE_METHOD(NativeBN, BN_mul, "(III)Z"),
538    NATIVE_METHOD(NativeBN, BN_mul_word, "(II)Z"),
539    NATIVE_METHOD(NativeBN, BN_new, "()I"),
540    NATIVE_METHOD(NativeBN, BN_nnmod, "(III)Z"),
541    NATIVE_METHOD(NativeBN, BN_set_negative, "(II)V"),
542    NATIVE_METHOD(NativeBN, BN_shift, "(III)Z"),
543    NATIVE_METHOD(NativeBN, BN_sub, "(III)Z"),
544    NATIVE_METHOD(NativeBN, BN_sub_word, "(II)Z"),
545    NATIVE_METHOD(NativeBN, ERR_error_string, "(I)Ljava/lang/String;"),
546    NATIVE_METHOD(NativeBN, ERR_get_error, "()I"),
547    NATIVE_METHOD(NativeBN, bitLength, "(I)I"),
548    NATIVE_METHOD(NativeBN, bn2litEndInts, "(I)[I"),
549    NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZI)Z"),
550    NATIVE_METHOD(NativeBN, longInt, "(I)J"),
551    NATIVE_METHOD(NativeBN, modifyBit, "(III)Z"),
552    NATIVE_METHOD(NativeBN, putLongInt, "(IJ)Z"),
553    NATIVE_METHOD(NativeBN, putULongInt, "(IJZ)Z"),
554    NATIVE_METHOD(NativeBN, sign, "(I)I"),
555    NATIVE_METHOD(NativeBN, twosComp2bn, "([BII)Z"),
556 };
register_java_math_NativeBN(JNIEnv * env)557 int register_java_math_NativeBN(JNIEnv* env) {
558     return jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
559 }
560