• 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 "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 {
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         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 
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     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 
NativeBN_twosComp2bn(JNIEnv * env,jclass cls,jbyteArray arr,int bytesLen,BIGNUM * ret)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 
NativeBN_longInt(JNIEnv * env,jclass,BIGNUM * a)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 
leadingZerosTrimmed(char * s)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 
NativeBN_BN_bn2dec(JNIEnv * env,jclass,BIGNUM * a)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 
NativeBN_BN_bn2hex(JNIEnv * env,jclass,BIGNUM * a)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 
NativeBN_BN_bn2bin(JNIEnv * env,jclass,BIGNUM * a)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 
NativeBN_bn2litEndInts(JNIEnv * env,jclass,BIGNUM * a)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 
NativeBN_sign(JNIEnv * env,jclass,BIGNUM * a)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 
NativeBN_BN_set_negative(JNIEnv * env,jclass,BIGNUM * b,int n)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 
NativeBN_bitLength(JNIEnv * env,jclass,BIGNUM * a)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 
NativeBN_BN_is_bit_set(JNIEnv * env,jclass,BIGNUM * a,int n)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 
NativeBN_modifyBit(JNIEnv * env,jclass,BIGNUM * a,int n,int op)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 
NativeBN_BN_shift(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,int n)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 
NativeBN_BN_add_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)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 
NativeBN_BN_sub_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)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 
NativeBN_BN_mul_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)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 
NativeBN_BN_div_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)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 
NativeBN_BN_mod_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)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 
NativeBN_BN_add(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)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 
NativeBN_BN_sub(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)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 
NativeBN_BN_gcd(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)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 
NativeBN_BN_mul(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)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 
NativeBN_BN_exp(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * p)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 
NativeBN_BN_div(JNIEnv * env,jclass,BIGNUM * dv,BIGNUM * rem,BIGNUM * m,BIGNUM * d)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 
NativeBN_BN_nnmod(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * m)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 
NativeBN_BN_mod_exp(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * p,BIGNUM * m)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 
NativeBN_BN_mod_inverse(JNIEnv * env,jclass,BIGNUM * ret,BIGNUM * a,BIGNUM * n)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 
NativeBN_BN_generate_prime_ex(JNIEnv * env,jclass,BIGNUM * ret,int bits,jboolean safe,BIGNUM * add,BIGNUM * rem,jint cb)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 
NativeBN_BN_is_prime_ex(JNIEnv * env,jclass,BIGNUM * p,int nchecks,jint cb)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 };
register_java_math_NativeBN(JNIEnv * env)556 void register_java_math_NativeBN(JNIEnv* env) {
557     jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
558 }
559